Re[20]: собеседование
От: elmal  
Дата: 05.02.10 12:31
Оценка: +1
Здравствуйте, LordMAD, Вы писали:

LMA>Ладно, объясню на наглядном примере: представь девайс который измеряет температуру и у тебя есть функция которая возвращает показание прибора в °С в виде целого числа. Прибор пусть будет с низкой точностью (например, он на базе термопары на эффекте Зеебека) — возвращает результат с точностью до 1°С. Помещаем прибор в комнату, где поддерживается постоянная температура с достаточной точностью. Вопрос: исправен ли прибор, если функция возвращает тебе сначала 20, а потом 21? Корректно ли проверять правильность прибора, надеясь, что он будет возвращать одинаковые значения при неизменной температуре которую он измеряет?

Мне страшно представить, во что превратится код, если для каждой из библиотечных функций мне придется беспокоиться о погрешности, и зависимости этой погрешности от входных параметров. Ну и далее — функция нахождения среднего, она имеет смысл для N элементов, а не для двух. Как ты будешь считать для трех элементов? А для пяти? Будешь хитрые спагетти из формул делать?
На практике лично я бы сделал так: Пытался бы привести к большему типу, а далее стандартной математической формулой (просуммировал и разделил на n. Прошу заметить — не на 2, а на n, так как программист должен знать 3 числа — 0, 1 и n). При необходимости кроссплатформенности — вначале проверил бы, что я действительно буду кастить к типу с большей разрядностью. Если компилятор не поддерживает типы с большей разрядностью, тут уже варианты. Самый простой — не допускать значений >= MAX_TYPE_VALUE/n. Если неприемлемо — вводил бы свои типы с большей разрядностью, а то и с неограниченной разрядностью. Но уж никак бы не стремился показать свои немерянные знания арифметики, что потом и сам черт ногу сломит в простейшем методе, и этой функцией пользоваться нельзя, так как из-за используемых хаков она округляет в случайную сторону. Но вообще, возникает вопрос — а почему в вашей мегафирме до сих пор нет библиотеки, которая вычисляет среднее? Почему каждый сотрудник обязан написать свою? Почему вы сами не в состоянии писать библиотеки, а доверяете это вновь прибывшим? Или у вас библиотек нет вообще? Библиотеки, вообще-то, пишутся достаточно редко, медленно, не в стрессовых условиях, и тщательно тестируются.

Да, кстати. Кого набираем и кто нужен? Я вот одно понял, кто действительно нужен работодателю. Это не тот, кто не ошибается в битах. Это не тот, кто знает язык назубок, включая подводные камни. А это тот, кто предугадывает проблемы на несколько лет вперед, и делая текущие таски пишет так, что чтоб если что надо было добавить — оно бы там уже было. Если каждый будет думать о будующем, будущее есть и у системы. А то иначе будет как у большинства — прекрасно работает система первый год, а через год сложность системы и объемы данных такими становятся, что тормозить не по детски все начинает, а оказывается, что фундамент забыли построить, а при добавлении новой функциональности забывали его укреплять. И намахнется все именно на продакшене, в самый ответственный момент. Учитесь у менеджеров — они всегда говорят, что программа должна быть написана так, чтобы если что потребовалось добавить или изменить, оно бы там уже было .
Re[24]: собеседование
От: shrecher  
Дата: 05.02.10 15:12
Оценка: +1
Здравствуйте, LordMAD, Вы писали:

I>>int avg(int a,int b)

I>>{
I>> return a/2 + b/2 + (a%2+b%2)/2;
I>>}

LMA>Да, это хорошее решение.


Увидил бы в коде такое "хорошее решение" заставил бы переписать.
Re[21]: собеседование
От: LordMAD Россия  
Дата: 06.02.10 17:47
Оценка:
Здравствуйте, elmal, Вы писали:

E>Здравствуйте, LordMAD, Вы писали:


LMA>>Ладно, объясню на наглядном примере: представь девайс который измеряет температуру и у тебя есть функция которая возвращает показание прибора в °С в виде целого числа. Прибор пусть будет с низкой точностью (например, он на базе термопары на эффекте Зеебека) — возвращает результат с точностью до 1°С. Помещаем прибор в комнату, где поддерживается постоянная температура с достаточной точностью. Вопрос: исправен ли прибор, если функция возвращает тебе сначала 20, а потом 21? Корректно ли проверять правильность прибора, надеясь, что он будет возвращать одинаковые значения при неизменной температуре которую он измеряет?


E>Мне страшно представить, во что превратится код, если для каждой из библиотечных функций мне придется беспокоиться о погрешности, и зависимости этой погрешности от входных параметров.


По сравнению с IEEE 754 — это мелочь.

E>функция нахождения среднего, она имеет смысл для N элементов, а не для двух.


Прежде всего, такая постановка задачи увеличила бы просто время собеседования.

E>На практике лично я бы сделал так: Пытался бы привести к большему типу, а далее стандартной математической формулой (просуммировал и разделил на n.


Выше в этой тему уже обсуждалось — поищи по ILP64.

E>Прошу заметить — не на 2, а на n, так как программист должен знать 3 числа — 0, 1 и n).


Ты слишком упрощаешь. Есть простые вещи, которые действительно имеет смысл реализовывать для n, а есть такие — для которых смысла в этом нет.

E>При необходимости кроссплатформенности — вначале проверил бы, что я действительно буду кастить к типу с большей разрядностью.


Это в этой теме уже обсуждалось. Как я уже писал, хорошее решение, если кандидат корректно использует статический assert. Но хуже, чем универсальное — усложняет подсчет времени на перенос системы на новую платформу.

E>Если компилятор не поддерживает типы с большей разрядностью, тут уже варианты. Самый простой — не допускать значений >= MAX_TYPE_VALUE/n.


Изменить Мир?
Постановка задачи — она не просто так, она из чего-то следует...

E>Если неприемлемо — вводил бы свои типы с большей разрядностью, а то и с неограниченной разрядностью. Но уж никак бы не стремился показать свои немерянные знания арифметики, что потом и сам черт ногу сломит в простейшем методе,


Зачем писать 2 строки включив мозг, когда можно написать 100 не включая его — это твой путь?

E>и этой функцией пользоваться нельзя, так как из-за используемых хаков она округляет в случайную сторону.


Почему же нельзя пользоваться? Если так рассуждать, так вообще никакой способ округления до целого нельзя использовать, а то вдруг кто-то ожидает еще какой-то способ округления.

E>Но вообще, возникает вопрос — а почему в вашей мегафирме до сих пор нет библиотеки, которая вычисляет среднее? Почему каждый сотрудник обязан написать свою?


Потому же, почему такой функции нет в стандартной библиотеке — потому что ad-hoc будет обладать преимуществами.

E>Почему вы сами не в состоянии писать библиотеки, а доверяете это вновь прибывшим? Или у вас библиотек нет вообще? Библиотеки, вообще-то, пишутся достаточно редко, медленно, не в стрессовых условиях, и тщательно тестируются.


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

E>Кого набираем и кто нужен? Я вот одно понял, кто действительно нужен работодателю. Это не тот, кто не ошибается в битах. Это не тот, кто знает язык назубок, включая подводные камни.


Таких просто не бывает. Ошибаются все. Искать нужно таких, которые не делают глупых ошибок.

E>А это тот, кто предугадывает проблемы на несколько лет вперед, и делая текущие таски пишет так, что чтоб если что надо было добавить — оно бы там уже было.


Ты имеешь в виду "оно должно быть готово к добавлению"? Или ты предлагаешь в рамках ресурсов, бюджета и времени для A, делать A+B?

E>Если каждый будет думать о будующем, будущее есть и у системы. А то иначе будет как у большинства — прекрасно работает система первый год, а через год сложность системы и объемы данных такими становятся, что тормозить не по детски все начинает, а оказывается, что фундамент забыли построить, а при добавлении новой функциональности забывали его укреплять. И намахнется все именно на продакшене, в самый ответственный момент.


Это вопрос вменяемости менеджмента, не более того.
Re[22]: собеседование
От: elmal  
Дата: 06.02.10 18:47
Оценка:
Здравствуйте, LordMAD, Вы писали:

LMA>По сравнению с IEEE 754 — это мелочь.

Как раз на практике IEEE 754 будет мелочью. Так как типы с ограниченной разрядностью как правила используются на значениях, далеких от предельно допустимых. Потому скорее всего на грабли даже не наступят.

LMA>Прежде всего, такая постановка задачи увеличила бы просто время собеседования.

Не увеличила бы. Решение практически тоже самое.

LMA>Выше в этой тему уже обсуждалось — поищи по ILP64.

Да хоть 128 или 256.

LMA>Ты слишком упрощаешь. Есть простые вещи, которые действительно имеет смысл реализовывать для n, а есть такие — для которых смысла в этом нет.

Смысла очень редко нет. Наиболее типичная ошибка — как раз сделать для двух вариантов. Или трех. А надо для N оказывается через год, а уже не поменять, на это заложились.

E>>При необходимости кроссплатформенности — вначале проверил бы, что я действительно буду кастить к типу с большей разрядностью.


LMA>Зачем писать 2 строки включив мозг, когда можно написать 100 не включая его — это твой путь?

Когда то я гордился, что знаю язык настолько хорошо, что для прочтения моего творчества требовалось очертененно включать мозг. С опытом понял, что код должен быть таким, чтобы при его чтении мозг не напрягался. А относительно типов с большей разрядностью — если в них появляется необходимость, а их нет, их надо вводить. Это потом многократно окупится, и не важно какое число строчек кода придется написать.

LMA>Почему же нельзя пользоваться? Если так рассуждать, так вообще никакой способ округления до целого нельзя использовать, а то вдруг кто-то ожидает еще какой-то способ округления.

Уже 100 раз об этом говорили.

LMA>Цель собеседования не в том, чтобы получить от кандидата код, который потом использовать, а в том, чтобы проверить определенные навыки у кандидата.

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

LMA>Таких просто не бывает. Ошибаются все. Искать нужно таких, которые не делают глупых ошибок.

Глупые ошибки тоже делают все. Более того, большинство ошибок как раз глупые. Так как когда делаешь простые вещи, ты в уверен что не допустишь ошибку, внимание расслаблено. А когда что-то сложнее, стараешься как раз максимально концентрироваться.

LMA>Ты имеешь в виду "оно должно быть готово к добавлению"? Или ты предлагаешь в рамках ресурсов, бюджета и времени для A, делать A+B?

Нет. Делать надо А так, чтобы когда потребовалось Б и В, их можно было сделать и код к этому был бы готов. То есть подумать, что потребоваться может в будующем, и если потребуется — как будем делать. Если решение есть, и не кривое, то делать. Если же А сделано так, что для добавление фичи Б потребуется все переписывать с нуля, или от этой фичи отказываться, или делать страшный костыль, то А сделано плохо. В твоем случае — фича А — посчитать среднее для 2-х чисел. А вот неизвестная фича Б, на которую нужно сразу же закладываться — это считать среднее для N чисел произвольного типа. Это в привычку должно войти — всегда думать на полтора шага вперед, или система развалится в будущем.

LMA>Это вопрос вменяемости менеджмента, не более того.

Как правило, у менеджмента хватает других забот, чтобы интересоваться что творится в коде. Под вменяемость должно подразумеваться не препятствовать наведению порядка в коде, а не руководство этим наведением.
Re[8]: собеседование
От: cpp_beginner  
Дата: 08.02.10 09:31
Оценка:
Здравствуйте, LordMAD, Вы писали:

LMA>Здравствуйте, Handie, Вы писали:


H>>int avg(int x, int y) { return (int)(((long long)x + y)/2); }


А если так?

template <typename T>
class simple_avg_traits{};

template <>
class simple_avg_traits<char>{
public:
    typedef int AccType;
};

template <>
class simple_avg_traits<short>{
public:
    typedef int AccType;
};


template <>
class simple_avg_traits<int>{
public:
    typedef long long AccType;
};

template <typename T> inline typename 
simple_avg_traits<T>::AccType traits_avg(const T a, const T b){
    typename simple_avg_traits<T>::AccType acc = a + b;
    return acc/2;
}
Re[4]: собеседование
От: Roman Odaisky Украина  
Дата: 08.02.10 09:48
Оценка:
Здравствуйте, LuciferSaratov, Вы писали:

H>>Ну и тест на "лоха" с << и | в цикле.


LS>Это если он совсем лох, будет << и |

LS>А чтобы работало, надо << и &

А не >> и &, случаем? (while(x) { result += x & 1; x >>= 1; }).

(Еще тут есть вариант с while(x) { x &= x-1; ++result; }.)
До последнего не верил в пирамиду Лебедева.
Re[17]: собеседование
От: Roman Odaisky Украина  
Дата: 08.02.10 09:52
Оценка: :)
Здравствуйте, FR, Вы писали:

SA>>
SA>>Func<string, string> revFunc = sourceStr => new string(sourceStr.ToCharArray().Reverse().ToArray());
SA>>

SA>>пользуйтесь :)) Количество использованных паттернов предлагаю посчитать самостоятельно :))
SA>>Как видим, нормальные языки позволяют сосредоточиться на логике, а не на том, как передвигать каждую из сорока ножек :))

FR>std::reverse(Str.begin(), Str.end());


do_something(s.rbegin(), s.rend())
До последнего не верил в пирамиду Лебедева.
Re[5]: собеседование
От: LuciferSaratov Россия  
Дата: 08.02.10 10:02
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, LuciferSaratov, Вы писали:


H>>>Ну и тест на "лоха" с << и | в цикле.


LS>>Это если он совсем лох, будет << и |

LS>>А чтобы работало, надо << и &

RO>А не >> и &, случаем? (while(x) { result += x & 1; x >>= 1; }).


RO>(Еще тут есть вариант с while(x) { x &= x-1; ++result; }.)


ну << можно заюзать хотя бы в этом варианте:

for (int i = 0; 1 << i < x; i++) {
  if (x & (1 << i)) {
    result++;
  }
}


А вот куда пристроить | — непонятно.
Re[23]: собеседование
От: LordMAD Россия  
Дата: 08.02.10 10:25
Оценка:
Здравствуйте, elmal, Вы писали:

LMA>>По сравнению с IEEE 754 — это мелочь.

E>Как раз на практике IEEE 754 будет мелочью. Так как типы с ограниченной разрядностью как правила используются на значениях, далеких от предельно допустимых. Потому скорее всего на грабли даже не наступят.

Как раз профессионально сделанные системы тем и отличаются от слеланных на коленке, что не расчитывают на "как правило" и "скорее всего".

LMA>>Прежде всего, такая постановка задачи увеличила бы просто время собеседования.

E>Не увеличила бы. Решение практически тоже самое.

Наверное, мы о разном говорим.

LMA>>Выше в этой тему уже обсуждалось — поищи по ILP64.

E>Да хоть 128 или 256.

Если ты про создание полноценного типа — это не на 1-2 минуты задание.

LMA>>Ты слишком упрощаешь. Есть простые вещи, которые действительно имеет смысл реализовывать для n, а есть такие — для которых смысла в этом нет.

E>Смысла очень редко нет. Наиболее типичная ошибка — как раз сделать для двух вариантов. Или трех. А надо для N оказывается через год, а уже не поменять, на это заложились.

Это всё зависит от конкретных задач. Для разных задач — статистика будет разная — когда есть смысл, а когда нет.

LMA>>Зачем писать 2 строки включив мозг, когда можно написать 100 не включая его — это твой путь?

E>Когда то я гордился, что знаю язык настолько хорошо, что для прочтения моего творчества требовалось очертененно включать мозг. С опытом понял, что код должен быть таким, чтобы при его чтении мозг не напрягался.

Концептуальная сложность задачи заключается не том, что может быть связано с C++ вообще, так что мозг все равно включать придется по другой причине. Бывают, конечно, и рутинные задачи, но это хорошее поле боя для junior'ов.

E>А относительно типов с большей разрядностью — если в них появляется необходимость, а их нет, их надо вводить. Это потом многократно окупится, и не важно какое число строчек кода придется написать.


Пример avg — это не тот случай когда их надо вводить.

LMA>>Почему же нельзя пользоваться? Если так рассуждать, так вообще никакой способ округления до целого нельзя использовать, а то вдруг кто-то ожидает еще какой-то способ округления.

E>Уже 100 раз об этом говорили.

Пока все доводы были в стиле "а вдруг...".

LMA>>Цель собеседования не в том, чтобы получить от кандидата код, который потом использовать, а в том, чтобы проверить определенные навыки у кандидата.

E>Навыки написания библиотек на скорость без тестирования в стрессовых условиях, работающих правильно с первого раза? Наверно есть у кого то эти навыки, не спорю. Но навык уж очень специфичный, и нужен в основном на собеседованиях.

Нет, навых не допускать UB на пустом месте. Понятно, что можно просто перевалить всё на тесты и потом героически исправлять баги... Только зачем, если можно нанять людей, который таких багов просто не допустят?

LMA>>Таких просто не бывает. Ошибаются все. Искать нужно таких, которые не делают глупых ошибок.

E>Глупые ошибки тоже делают все. Более того, большинство ошибок как раз глупые. Так как когда делаешь простые вещи, ты в уверен что не допустишь ошибку, внимание расслаблено. А когда что-то сложнее, стараешься как раз максимально концентрироваться.

Мягко говоря, в такой ситуации явно проблема распределения обязанностей.

LMA>>Ты имеешь в виду "оно должно быть готово к добавлению"? Или ты предлагаешь в рамках ресурсов, бюджета и времени для A, делать A+B?

E>Нет. Делать надо А так, чтобы когда потребовалось Б и В, их можно было сделать и код к этому был бы готов. То есть подумать, что потребоваться может в будующем, и если потребуется — как будем делать. Если решение есть, и не кривое, то делать. Если же А сделано так, что для добавление фичи Б потребуется все переписывать с нуля, или от этой фичи отказываться, или делать страшный костыль, то А сделано плохо.

Это верно, при условии, что рефакторинг обойдется дороже, что зависит от конкретной ситуации.

E>В твоем случае — фича А — посчитать среднее для 2-х чисел. А вот неизвестная фича Б, на которую нужно сразу же закладываться — это считать среднее для N чисел произвольного типа.


Чушь, потому что универтальная функция будет хуже по определенным критериям, чем ad hoc.

E>Это в привычку должно войти — всегда думать на полтора шага вперед, или система развалится в будущем.


Чтобы система не развалилась, нужно просто иметь нормальную архитектуру.

E>>>Если каждый будет думать о будующем, будущее есть и у системы. А то иначе будет как у большинства — прекрасно работает система первый год, а через год сложность системы и объемы данных такими становятся, что тормозить не по детски все начинает, а оказывается, что фундамент забыли построить, а при добавлении новой функциональности забывали его укреплять. И намахнется все именно на продакшене, в самый ответственный момент.

LMA>>Это вопрос вменяемости менеджмента, не более того.
E>Как правило, у менеджмента хватает других забот, чтобы интересоваться что творится в коде. Под вменяемость должно подразумеваться не препятствовать наведению порядка в коде, а не руководство этим наведением.

Код тут не причем. Если "фундамент забыли построить" — значит или архитектуры нет или она никуда не годится, то есть не были назначены ответственные за неё или не те люди были назначены ответственными — то есть менеджмент не выполнил свою непосредственную работу. Аналогично и про поддержание архитектуры в актуальном состоянии.

Вообще, это не работа программистов — исправлять и предугадывать косяки менеджмента, как любое другое лечение симптомов.
Re[9]: собеседование
От: LordMAD Россия  
Дата: 08.02.10 10:41
Оценка:
Здравствуйте, cpp_beginner, Вы писали:

_>А если так?


_>
_>template <typename T>
_>class simple_avg_traits{};

_>template <>
_>class simple_avg_traits<char>{
_>public:
_>    typedef int AccType;
_>};

_>template <>
_>class simple_avg_traits<short>{
_>public:
_>    typedef int AccType;
_>};


_>template <>
_>class simple_avg_traits<int>{
_>public:
_>    typedef long long AccType;
_>};

_>template <typename T> inline typename 
_>simple_avg_traits<T>::AccType traits_avg(const T a, const T b){
_>    typename simple_avg_traits<T>::AccType acc = a + b;
_>    return acc/2;
_>}
_>


Как минимум, такие проблемы:
1. Не вполне корректное поведение, если будут переданы в качестве аргументов типы, которые могут быть неявно преобразованы к int, но для которых нет специализации.
2. Функция возвращает не const T и даже не T, хотя для данного случая const T — достаточно. В принципе к const я бы на собеседовании может сильно не придирался бы, хотя, с другой стороны, такое решение провоцирует задать соответствующий вопрос.
3. Все равно нужна проверка, что размер long long больше, чем int (а не равен). И при таком решении еще и, что int больше, чем short и char.
Re[10]: собеседование
От: cpp_beginner  
Дата: 08.02.10 11:09
Оценка:
Здравствуйте, LordMAD, Вы писали:


LMA>Как минимум, такие проблемы:

LMA>1. Не вполне корректное поведение, если будут переданы в качестве аргументов типы, которые могут быть неявно преобразованы к int, но для которых нет специализации.

В специализации по умолчанию сделать assert(), добавить специализаций по вкусу

LMA>2. Функция возвращает не const T и даже не T, хотя для данного случая const T — достаточно. В принципе к const я бы на собеседовании может сильно не придирался бы, хотя, с другой стороны, такое решение провоцирует задать соответствующий вопрос.


А почему должна возвращать const T?

LMA>3. Все равно нужна проверка, что размер long long больше, чем int (а не равен). И при таком решении еще и, что int больше, чем short и char.


Вроде тоже решается ассертом. Хотя наверно как-нибудт можно намутить проверку при спциализации, применить SFINAE например.
Re[24]: собеседование
От: elmal  
Дата: 08.02.10 11:41
Оценка: 1 (1) +1
Здравствуйте, LordMAD, Вы писали:

LMA>Наверное, мы о разном говорим.

Хорошо, напиши мне avg для 5 аргументов. Решение, которое привел ты для двух, для большего числа аргументов уже не годится. И если будешь проверять на чет-нечет с кучей if, то есть у меня большие подозрения в том, что они ко всему прочему будет крайне неэффективно. Неэффективен именно алгоритм.

LMA>Если ты про создание полноценного типа — это не на 1-2 минуты задание.

То, что ты назвал — это тоже не на 1-2 минуты задание. Там очень неприятные подводные камни, которые в реальности редки. Даже если видишь их, не факт что сходу наиболее эффективно обойдешь. За 1-2 минуты это сделают без ошибок те, кто к этому заданию готов. Даже у тебя его сделать не получилось, хоть ты и задаешь его на собеседовании. У большинства тоже на этом форуме не получилось без ошибок, хоть они и более правильное решение выдали, чем твое (a/2+b/2 гораздо лучше во всех отношениях, например, хоть и не всегда работает идеально).

LMA>Пример avg — это не тот случай когда их надо вводить.

Если что-то потребовалось 1 раз, значит потребуется еще много раз. Делаете много вычислений с типами ограниченной разрядности — рано или поздно придется вводить. Или avg и не нужна вовсе. А если умножать потребуется, а потом разделить?

LMA>Пока все доводы были в стиле "а вдруг...".

Вдруг в реальных ситуациях всегда встречается. Если что-то может случиться, оно случится. У тебя тоже доводы в стиле "а вдруг". Непонятно зачем тебе понадобилась мегафункция, которая должна корректно отрабатывать на любых целых и для любых платформ.

LMA>Нет, навых не допускать UB на пустом месте. Понятно, что можно просто перевалить всё на тесты и потом героически исправлять баги... Только зачем, если можно нанять людей, который таких багов просто не допустят?

Последний раз, когда мне приходилось помнить про UB, было еще тогда, когда я еще на ассемблере писал. С переходом на языки высокого уровня мне ни разу не приходилось встречаться с ситуациями, где надо было думать про UB. Мне как то странным видится, что у вас риск UB настолько велик, что это критическая вещь. Настолько это важно, что готовы пожертвовать коммутативностью, что потом сравнивать результаты вообще нельзя.

LMA>Мягко говоря, в такой ситуации явно проблема распределения обязанностей.

Нет такой проблемы. Есть проблема человеческой природы. Люди не машины, и ошибаются. Могу ошибиться и в простых вещах тоже.

LMA>Это верно, при условии, что рефакторинг обойдется дороже, что зависит от конкретной ситуации.

Рефакторинг обычно всегда забывают делать, пока не приспичит. И когда уже без него никак, он объодится очень дорого.

LMA>Чушь, потому что универтальная функция будет хуже по определенным критериям, чем ad hoc.

В основном она хуже по критериям скорости. Одно но — если тебя так беспокоит кроссплатформенность, то универсальное решение даже простой задачи с максимальной скоростью тебе не сделать. И затачивать надо под конкретную платформу. Вплоть до написания этого критического участка кода на ассемблере, с кучей флагов условной компиляции. Это делается никак не на собеседованиях в стрессовых режимах, и далеко не всегда вот такая оптимизация очень хорошая идея.

LMA>Чтобы система не развалилась, нужно просто иметь нормальную архитектуру.

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

LMA>Вообще, это не работа программистов — исправлять и предугадывать косяки менеджмента, как любое другое лечение симптомов.

У менеджмена косяки были, есть и будут всегда. По простой причине, что они физически не могут уследить за всем. Особенно если они очень давно в последний раз код видели. Потому исправлять косяки менеджмента — это основное в работе программиста. Если не предугадаешь, и будешь делать слепо по инструкции, система развалится. Вариант с тупыми исполнителями в разработке не работает, хоть ты тресни, или работает на коротком промежутке времени, а потом все переделывать.
Re[11]: собеседование
От: LordMAD Россия  
Дата: 08.02.10 11:46
Оценка: 1 (1)
Здравствуйте, cpp_beginner, Вы писали:

LMA>>1. Не вполне корректное поведение, если будут переданы в качестве аргументов типы, которые могут быть неявно преобразованы к int, но для которых нет специализации.


_>В специализации по умолчанию сделать assert(),


Этого недостаточно.

_>добавить специализаций по вкусу


За ради чего? Если уж хотелось сделать реализацию для char и short, достаточно было просто перегруженных функций.

LMA>>2. Функция возвращает не const T и даже не T, хотя для данного случая const T — достаточно. В принципе к const я бы на собеседовании может сильно не придирался бы, хотя, с другой стороны, такое решение провоцирует задать соответствующий вопрос.


_>А почему должна возвращать const T?


const потому что rvalue. T — потому что его достаточно и это есть в постановке задачи.

LMA>>3. Все равно нужна проверка, что размер long long больше, чем int (а не равен). И при таком решении еще и, что int больше, чем short и char.

_>Вроде тоже решается ассертом. Хотя наверно как-нибудт можно намутить проверку при спциализации, применить SFINAE например.

Решается только если не надо поддерживать платформы, на которых размеры равны.
Re[25]: собеседование
От: LordMAD Россия  
Дата: 08.02.10 14:01
Оценка:
Здравствуйте, elmal, Вы писали:

LMA>>>>Прежде всего, такая постановка задачи увеличила бы просто время собеседования.

E>>>Не увеличила бы. Решение практически тоже самое.
LMA>>Наверное, мы о разном говорим.
E>Хорошо, напиши мне avg для 5 аргументов.



E>Решение, которое привел ты для двух, для большего числа аргументов уже не годится.


Да, и что?
А еще нормальные люди покупают для личных нужд легковые автомобили, а не автобусы. Призываешь заняться разработкой универсального решения — чтобы и как легковушка, и чтобы 50 человек возить можно было, и чтобы как самосвал можно было использовать?

Как я писал с самого начала — этот вопрос именно по С/C++, не про алгоритмы и не про проектирование. Ты же пытаешься утверждать, что проектирование важнее знания языка. Так вот: во-первых, эта задачка не имеет к этому никакого отношения (она имеет отношение конкретно к знанию языка), а во-вторых, не надо сравнивать синее и мягким.

E>И если будешь проверять на чет-нечет с кучей if, то есть у меня большие подозрения в том, что они ко всему прочему будет крайне неэффективно. Неэффективен именно алгоритм.


Давай я тебе на более очевидном примере поясню: сортировку двух чисел делают чем-то вроде if (a>b) swap(a, b);
Так вот: делать по этому алгоритму сортировку n чисел — не эффективно. А делать сортировку двух чисел алгоритмом, который хорош для сортировки n чисел — тоже неэффективно.

LMA>>Если ты про создание полноценного типа — это не на 1-2 минуты задание.

E>То, что ты назвал — это тоже не на 1-2 минуты задание. Там очень неприятные подводные камни, которые в реальности редки. Даже если видишь их, не факт что сходу наиболее эффективно обойдешь. За 1-2 минуты это сделают без ошибок те, кто к этому заданию готов.

Это задание именно на 1-2 минуты. И его цель — отсеять тех, кто сходу не видит проблемы в бездумном сложении двух int и тех, кто не знает когда безопасно можно заменять деление на степень двойки, а когда нельзя.

E>Даже у тебя его сделать не получилось, хоть ты и задаешь его на собеседовании. У большинства тоже на этом форуме не получилось без ошибок, хоть они и более правильное решение выдали, чем твое (a/2+b/2 гораздо лучше во всех отношениях, например, хоть и не всегда работает идеально).


Не передергивай! Во-первых, я привел лишь вариант решения, который считаю нормальным. Никто меня не переубедил, что это решение чем-то плохо, при такой формулировке задания и ни одного серьезного довода я не увидел пока в этой теме. То, что кто-то чего-то ожидает от функции, чего нет в её контракте — это не аргумент. С тем же успехом можно жаловаться на то, что max(a, b) = 0 и max(b, a) = 0 дадут разные результаты при a == b.
В любом случае, от кандидата никто не требует идеального решения (его, кстати, нет) — требуется показать, что он владеет определенными навыками.

LMA>>Пример avg — это не тот случай когда их надо вводить.

E>Если что-то потребовалось 1 раз, значит потребуется еще много раз. Делаете много вычислений с типами ограниченной разрядности — рано или поздно придется вводить. Или avg и не нужна вовсе.

А ничего такого, вроде чисел с большей разрядностью в этом случае и не требовалось даже 1 раз.

E>А если умножать потребуется, а потом разделить?


Зависит от... Может быть "изобрету велосипед", может быть воспользуюсь какой-то сторонней библиотекой... Все это зависит об множества обстоятельств, которые будут известны когда "умножать потребуется, а потом разделить".

LMA>>Пока все доводы были в стиле "а вдруг...".

E>Вдруг в реальных ситуациях всегда встречается. Если что-то может случиться, оно случится.

Ну да — все люди умирают от падения кирпича на голову.

E>У тебя тоже доводы в стиле "а вдруг". Непонятно зачем тебе понадобилась мегафункция, которая должна корректно отрабатывать на любых целых и для любых платформ.


Ссылку, пожалуйста, — что ты конкретно имеешь в виду.

Еще раз повторю: нужна не функция — нужны люди, которые умеют писать сходу платформонезависимый надежный код.

LMA>>Нет, навых не допускать UB на пустом месте. Понятно, что можно просто перевалить всё на тесты и потом героически исправлять баги... Только зачем, если можно нанять людей, который таких багов просто не допустят?

E>Последний раз, когда мне приходилось помнить про UB, было еще тогда, когда я еще на ассемблере писал.

Давай поподробнее про UB из стандартов C/C++, с которыми ты сталкивался "когда я еще на ассемблере писал"?

E>С переходом на языки высокого уровня мне ни разу не приходилось встречаться с ситуациями, где надо было думать про UB.


И ты решил, что раз ты не сталкивался, то никто не сталкивается?

E>Мне как то странным видится, что у вас риск UB настолько велик, что это критическая вещь. Настолько это важно, что готовы пожертвовать коммутативностью, что потом сравнивать результаты вообще нельзя.


А я вообще не вижу причин не жертвовать тем, что не требуется. И в данном конкретном случае — сравнивать результаты можно.

LMA>>>>Таких просто не бывает. Ошибаются все. Искать нужно таких, которые не делают глупых ошибок.

E>>>Глупые ошибки тоже делают все. Более того, большинство ошибок как раз глупые. Так как когда делаешь простые вещи, ты в уверен что не допустишь ошибку, внимание расслаблено. А когда что-то сложнее, стараешься как раз максимально концентрироваться.
LMA>>Мягко говоря, в такой ситуации явно проблема распределения обязанностей.
E>Нет такой проблемы. Есть проблема человеческой природы. Люди не машины, и ошибаются. Могу ошибиться и в простых вещах тоже.

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

LMA>>Это верно, при условии, что рефакторинг обойдется дороже, что зависит от конкретной ситуации.

E>Рефакторинг обычно всегда забывают делать, пока не приспичит. И когда уже без него никак, он объодится очень дорого.

Это называется — бардак. Грубо говоря, если применяются design review и code review, такая ситуация не должна возникать в принципе. Так что ни разу это не "обычно всегда".

LMA>>Чушь, потому что универтальная функция будет хуже по определенным критериям, чем ad hoc.

E>В основном она хуже по критериям скорости.

Совершенно не обязательно. Она может быть и сложнее в реализации (как в твоём примере с введением типа с большей разрадностью, например) и менее удобной для сопровождения и модификации (повысить скорость в 2 раза для твоего примера с введением типа с большей разрадностью, например), требовать больше документации, сложнее тестироваться, требовать больше времени на разработку (что вообще типично для универсальных решений).

LMA>>Чтобы система не развалилась, нужно просто иметь нормальную архитектуру.

E>Архитектура в начале обычно всегда нормальная, заточенная под конкретную задачу. А при развитии системы уже начинаются особенности. Потому если при изменении требований не укреплять фундамент, система рухнет.

Если развитие системы идет не тем путем, который заложен в архитектуре, значит либо плохая архитектура, либо идёте не тем путем, которым следует (с учетом наличия именно такой архитектуры). Если фундамент дома имеет определнную форму, а стоить здание хотим другой формы — надо либо менять фундамент, либо строить здание как планировалось.


LMA>>Вообще, это не работа программистов — исправлять и предугадывать косяки менеджмента, как любое другое лечение симптомов.

E>У менеджмена косяки были, есть и будут всегда. По простой причине, что они физически не могут уследить за всем. Особенно если они очень давно в последний раз код видели. Потому исправлять косяки менеджмента — это основное в работе программиста. Если не предугадаешь, и будешь делать слепо по инструкции, система развалится. Вариант с тупыми исполнителями в разработке не работает, хоть ты тресни, или работает на коротком промежутке времени, а потом все переделывать.



Поработаешь с вменяемым менеджментом — узнаешь "страшную" правду.
Re[26]: собеседование
От: elmal  
Дата: 08.02.10 16:24
Оценка: +1
Здравствуйте, LordMAD, Вы писали:

LMA>Как я писал с самого начала — этот вопрос именно по С/C++, не про алгоритмы и не про проектирование. Ты же пытаешься утверждать, что проектирование важнее знания языка.

Начнем с того, что это вопрос совсем не по языку. Так как теже самые грабли будут на VB, Forth, Nemerle, ассемблере наконец. Эта задача на то, знает человек внутреннее представление чисел или не знает, больше не проверяет ничего. Не уверен я, кстати, что на абсолютно всех платформах внутреннее представление чисел будет одинаковым. А там, где представление будет отличаться, там очень большая вероятность, что компилятор Си будет заточен именно под особенности платформы, и плевать ему на стандарты. Си это низкоуровневый язык, вообще-то. Ну и закончим тем, что язык изучается очень быстро, более того, глубокое знание языка на практике требуется очень и очень редко.

LMA>В любом случае, от кандидата никто не требует идеального решения (его, кстати, нет) — требуется показать, что он владеет определенными навыками.

a/2+b/2 пойдет за нормальное решение? Или промежуточный кастинг к большему пройдет за нормальное решение? Если да, то хорошо. Если нет — тут уже очень большие вопросы.

LMA>Давай поподробнее про UB из стандартов C/C++, с которыми ты сталкивался "когда я еще на ассемблере писал"?

При чем здесь стандарты конкретного языка? Проблема, которую ты пытаешься отловить, она от языка не зависит вообще. Если только язык не оперирует исключительно с числами неограниченной разрядности.

LMA>А я вообще не вижу причин не жертвовать тем, что не требуется. И в данном конкретном случае — сравнивать результаты можно.

Можно спросить, как сравнивать результаты? Я вижу один путь, вводить функцию isEquals(int a, int b), возвращающую true если разница между аргументами не превышает 1. Как минимум очень спорное решение, погрешность схлопочем на пустом месте. Для нормального сравнения целых она не годится, потому функцию придется назвать isAvgEquals(int a, int b), что маразм, вообще-то. Да и не спасет эта функция, придется рассчитывать на внимательность, что вызовут ее, а не оператор сравнения, что является стандартом для целочисленных типов.
Re[27]: собеседование
От: LordMAD Россия  
Дата: 10.02.10 07:53
Оценка:
Здравствуйте, elmal, Вы писали:

LMA>>Как я писал с самого начала — этот вопрос именно по С/C++, не про алгоритмы и не про проектирование. Ты же пытаешься утверждать, что проектирование важнее знания языка.

E>Начнем с того, что это вопрос совсем не по языку. Так как теже самые грабли будут на VB, Forth, Nemerle, ассемблере наконец. Эта задача на то, знает человек внутреннее представление чисел или не знает, больше не проверяет ничего. Не уверен я, кстати, что на абсолютно всех платформах внутреннее представление чисел будет одинаковым.

Грабли будут разные, потому что на том же ассемблере, поведение будет детерминированным, в отличие от C/C++, где будет UB. Соответственно при UB будет большая разница в том, как обрабатывается integer overflows в конкретной версии компилятора и на конкретной платформе и с конкретными параметрами компиляции. Соответственно, применительно к C++, приходим даже к теме гарантий безопасности исключений Абрамса. Могу конечно, предположить, что ты считаешь, что и безопасный относительно исключений код писать "на практике требуется очень и очень редко"?

E>А там, где представление будет отличаться, там очень большая вероятность, что компилятор Си будет заточен именно под особенности платформы, и плевать ему на стандарты. Си это низкоуровневый язык, вообще-то.


Я конечно понимаю, что ты думаешь, что если ты пишешь код, который будет компилироваться только одним компилятором, то у всех такой же быдлокодинг. А вот представляешь — не у всех так.
Соответственно, хотя производитель компилятора и может учитывать особенности платформ на которых работает их компилятор, то программист должен уметь писать код таким образом, чтобы он корректно работал на всех платформах, на которых требуется.

Кстати, я не совсем понял — ты иммешь в виду, что C и C++ — низкоуровневые языки или просто передергиваешь, пытаясь сделать вид, что мы говорим о C, а не о C и C++?

E>Ну и закончим тем, что язык изучается очень быстро, более того, глубокое знание языка на практике требуется очень и очень редко.


Во-первых, язык изучается быстро только в объеме, достаточным для быдлокодинга, а во всех остальных случаев его обычно изучают годами, по крайней мере.

Во-вторых, если уж ты пытаешься какую-то статистику приводить относительно того, как как ачсто требуется "глубокое знание языка", то будь добр приводить ссылку — откуда у тебя такая странная статистика взялась.
Ну а в данном конкретном случае, ты, видимо пытаешься доказать что приведенная тобой статистика верна не просто для индустрии, а конкретно для моей конторы... Забавно, что ты пытаешься мне это сообщить!

LMA>>В любом случае, от кандидата никто не требует идеального решения (его, кстати, нет) — требуется показать, что он владеет определенными навыками.

E>a/2+b/2 пойдет за нормальное решение? Или промежуточный кастинг к большему пройдет за нормальное решение? Если да, то хорошо. Если нет — тут уже очень большие вопросы.

Я уже привел решение, которое я считаю нормальным — это решение, которое кандидаты дают именно за 1-2 минуты.
a/2+b/2 дает неверный результат для двух нечетных чисел, а casting к большему — нормальный если casting происходит к большему (а не просто к long long или double).

LMA>>Давай поподробнее про UB из стандартов C/C++, с которыми ты сталкивался "когда я еще на ассемблере писал"?

E>При чем здесь стандарты конкретного языка? Проблема, которую ты пытаешься отловить, она от языка не зависит вообще. Если только язык не оперирует исключительно с числами неограниченной разрядности.

При том, что программисту придется писать на конкретном языке. Соответственно мы берем на работу тех, кто его знает. Как я уже написал выше, эта "проблема" проявляется в C/C++ как UB, в то время как ассемблере такая же ситуация проявляется по-другому.

Я все еще жду про UB из стандартов C/C++, с которыми ты сталкивался "когда я еще на ассемблере писал" (выделил).

LMA>>А я вообще не вижу причин не жертвовать тем, что не требуется. И в данном конкретном случае — сравнивать результаты можно.

E>Можно спросить, как сравнивать результаты? Я вижу один путь, вводить функцию isEquals(int a, int b), возвращающую true если разница между аргументами не превышает 1. Как минимум очень спорное решение, погрешность схлопочем на пустом месте. Для нормального сравнения целых она не годится, потому функцию придется назвать isAvgEquals(int a, int b), что маразм, вообще-то. Да и не спасет эта функция, придется рассчитывать на внимательность, что вызовут ее, а не оператор сравнения, что является стандартом для целочисленных типов.

Если сравнивать результаты нужно — правильный способ — это оговорить в требованиях к функции вопрос округления до целого.
Если по каким-то причинам так сделать не удастся — можно и костыль использовать, но тогда сравнивать разницу нужно не с 1, а c величиной, зависящей, от a и b. Причем это именно костыль, который лечит симптом, а болезнь в том, что кто-то знал, что надо часто сравнивать результаты функции, но не включил это в требования к функции.
Re[28]: собеседование
От: elmal  
Дата: 10.02.10 09:17
Оценка:
Здравствуйте, LordMAD, Вы писали:

LMA>Грабли будут разные, потому что на том же ассемблере, поведение будет детерминированным, в отличие от C/C++, где будет UB. Соответственно при UB будет большая разница в том, как обрабатывается integer overflows в конкретной версии компилятора и на конкретной платформе и с конкретными параметрами компиляции. Соответственно, применительно к C++, приходим даже к теме гарантий безопасности исключений Абрамса. Могу конечно, предположить, что ты считаешь, что и безопасный относительно исключений код писать "на практике требуется очень и очень редко"?

Ассемблеры, они разные. И в общем случае на разных ассемблерах поведение ни черта не детерминировано тоже. Я, например, знал как минимум 4 системы команд разных процессоров. Когда знал только один процессор, для меня было все детерминировано. Когда стал знать несколько — стал мыслить более высокоуровнево. Как результат, из ассемблера я вырос. А начинал я как раз с ассемблера. По поводу безопасного кода в плане исключений — это зависит от того, что под ним подразумевается. Если пишешь под разными компиляторами под любыми платформами, то самый безопасный путь — не использовать исключений вообще, так как не все компиляторы их поддерживают. И плевать куче компиляторов на стандарты, это рекомендация, а не факт. Здравый смысл надо иметь, а не стандарты цитировать, и все хорошо будет.

LMA>Я конечно понимаю, что ты думаешь, что если ты пишешь код, который будет компилироваться только одним компилятором, то у всех такой же быдлокодинг. А вот представляешь — не у всех так.

Все то, что не связано с тем, чем занимаешься ты — то быдлокодинг, знакомый образ мыслей . Советую пару раз сменить специализацию, язык и т.д. — и твое мировоззрение поменяется. Сам через такое прошел, раньше думал точно так же, как и ты. Как разработчик вырастешь неимоверно. Кругозор очень хорошая штука. Те задачи, которые выполняешь сейчас — будешь выполнять быстрее, качественнее в смысле поддержки и надежнее. Одна беда будет — не пройдешь собственного собеседования .

LMA>Кстати, я не совсем понял — ты иммешь в виду, что C и C++ — низкоуровневые языки или просто передергиваешь, пытаясь сделать вид, что мы говорим о C, а не о C и C++?

Я не видел в задаче ничего, что относилось бы к С++. Чистый Си.

LMA>Во-первых, язык изучается быстро только в объеме, достаточным для быдлокодинга, а во всех остальных случаев его обычно изучают годами, по крайней мере.

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

LMA>Во-вторых, если уж ты пытаешься какую-то статистику приводить относительно того, как как ачсто требуется "глубокое знание языка", то будь добр приводить ссылку — откуда у тебя такая странная статистика взялась.

Относительно статистики. Я уже читал про твое крайне негативное отношение к Макконелу. Например ты высказывался против замены magic numbers на константы, ты за усложнение кода и т.д. Я представляю соответственно, в каком стиле у вас код написан. И да, именно при таком коде основное — это как раз знание языка. Плюс очертененная внимательность тоже основное. Что могу сказать, система, насколько я понимаю, у вас пока держится, но рано или поздно столкнетесь с тем, что поддерживать ее будете не в силах даже сами. Польза писать понятно уже давно доказана, best practices тоже уже давно выработаны, то, что это игнорируем — это до ткх пор, пока конкуренты не появятся. А я наблюдал, как из-за того, что в коде ни черта не разобраться, компания (пионер в своей области) поглощалась конкурентом.

LMA>Я уже привел решение, которое я считаю нормальным — это решение, которое кандидаты дают именно за 1-2 минуты.

LMA>a/2+b/2 дает неверный результат для двух нечетных чисел, а casting к большему — нормальный если casting происходит к большему (а не просто к long long или double).
Большинство людей на этом форуме считают твое решение ненормальным. Тебя еще никто не поддержал. Одни неучи в индустрии сидят, как я понимаю?

LMA>Я все еще жду про UB из стандартов C/C++, с которыми ты сталкивался "когда я еще на ассемблере писал" (выделил).

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

LMA>Если по каким-то причинам так сделать не удастся — можно и костыль использовать, но тогда сравнивать разницу нужно не с 1, а c величиной, зависящей, от a и b. Причем это именно костыль, который лечит симптом, а болезнь в том, что кто-то знал, что надо часто сравнивать результаты функции, но не включил это в требования к функции.

Вот это вообще жесть . Представляю что у вас там в требованиях творится, если такое надо включать. На 1 строчку кода 100 строк документации, я так понимаю? Результаты нужно ведь не только сравнивать, но и делить на них, умножать, возводить в степень и т.д. Итого — надо для каждой функции писать теперь что с результатом делать можно, а что нет ? Всегда считал, что не дело функции знать, как будет использоваться ее результат. Базовый принцип это, вообще то. Если можно результат использовать неправильно, он будет использован неправильно. И никакая кипа документации не поможет. Если этот принцип нарушать — крупную сложную систему не построить, даже на средней все рухнет.
Re[29]: собеседование
От: LordMAD Россия  
Дата: 10.02.10 12:14
Оценка:
Здравствуйте, elmal, Вы писали:

LMA>>Грабли будут разные, потому что на том же ассемблере, поведение будет детерминированным, в отличие от C/C++, где будет UB. Соответственно при UB будет большая разница в том, как обрабатывается integer overflows в конкретной версии компилятора и на конкретной платформе и с конкретными параметрами компиляции. Соответственно, применительно к C++, приходим даже к теме гарантий безопасности исключений Абрамса. Могу конечно, предположить, что ты считаешь, что и безопасный относительно исключений код писать "на практике требуется очень и очень редко"?

E>Ассемблеры, они разные. И в общем случае на разных ассемблерах поведение ни черта не детерминировано тоже. Я, например, знал как минимум 4 системы команд разных процессоров. Когда знал только один процессор, для меня было все детерминировано. Когда стал знать несколько — стал мыслить более высокоуровнево.

Ты имел один исходник на ассемблере, из которого получал программу для 4 различных процессоров? Если нет — то к чему это ты?

E>По поводу безопасного кода в плане исключений — это зависит от того, что под ним подразумевается. Если пишешь под разными компиляторами под любыми платформами, то самый безопасный путь — не использовать исключений вообще, так как не все компиляторы их поддерживают.


Что с того, что исключения не поддерживают старые компиляторы? Если так рассуждать — надо вообще отказываться от половины C++, включая шаблоны, using и прочее. В тех случаях когда переносимость имеет наивысший приоритет, лучше просто использовать чистый С, причем желательно не C99, а K&R. Отказываться от исключений в C++ можно, когда речь идет о небольших автономных поделках, так например поступает google с их open-source проектиками. А вот в полноценных проектах так делать не стоит, потому что иначе придется иметь дело только с "наибольшим общим делителем" возможностей, а для систем нормальных размеров проще на новую платформу подходящий компилятор портировать или от платформы отказаться.

E>Все то, что не связано с тем, чем занимаешься ты — то быдлокодинг, знакомый образ мыслей .


А ты объясни — почему ты считаешь что из того что компилятор заточен под платформу, следует что и код заточен под платформу. Я это кроме как тем что ты пишешь код, который будет компилироваться только одним компилятором, ничем другим объяснить это не могу.

LMA>>Кстати, я не совсем понял — ты иммешь в виду, что C и C++ — низкоуровневые языки или просто передергиваешь, пытаясь сделать вид, что мы говорим о C, а не о C и C++?

E>Я не видел в задаче ничего, что относилось бы к С++. Чистый Си.

То есть то, что справедливо и для C, человек, который программирует на C++ знать не должен?

E>>>Ну и закончим тем, что язык изучается очень быстро, более того, глубокое знание языка на практике требуется очень и очень редко.

LMA>>Во-первых, язык изучается быстро только в объеме, достаточным для быдлокодинга, а во всех остальных случаев его обычно изучают годами, по крайней мере.
E>Те, кто в совершенстве знают язык, часто тоже очень и очень сильно быдлокодят. Быдлокодинг от знания языка не зависит. Более того, чем лучше знаешь язык, тем более опасные вещи сможешь натворить. В Си, например, с указателями такое можно наворотить, что это потом без поллитра ну никак не прочитать. А в С++ возможностей накреативить на порядок больше. А через полгода сам в своем творчестве не разберешься.

Есть старая истина: the only valid measurement of code quality: WTFs/minute. Опять возвращаемся к design review и code review. Короче говоря — то о чем ты пишешь — не проблема, если бардака нет.

LMA>>Во-вторых, если уж ты пытаешься какую-то статистику приводить относительно того, как как ачсто требуется "глубокое знание языка", то будь добр приводить ссылку — откуда у тебя такая странная статистика взялась.

E>Относительно статистики. Я уже читал про твое крайне негативное отношение к Макконелу.

Отнюдь — Стив Макконнелл (Steve McConnell), которого ты неуважаешь до такой степени, что даже фамилию его переврал, — много чего умного понаписал. Это, само собой, не означает, что каждое его слово надо понимать буквально.
И какое это имеет отношение к статистике?

E>Например ты высказывался против замены magic numbers на константы, ты за усложнение кода и т.д. Я представляю соответственно, в каком стиле у вас код написан.


Ни в коем разе. Я лишь писал, что есть константы (0, 1, 0xDEADBEEF и т.п.), которые в числовом выражении могут быть читабельнее, чем те имена, которые могут назначить соответствующим константам.
И какое это имеет отношение к статистике?

E>И да, именно при таком коде основное — это как раз знание языка.


При каком коде?

E>Польза писать понятно уже давно доказана, best practices тоже уже давно выработаны, то, что это игнорируем — это до ткх пор, пока конкуренты не появятся.


А кто-то выступал за то, чтобы писать непонятно?
И какое это имеет отношение к статистике?

E>А я наблюдал, как из-за того, что в коде ни черта не разобраться, компания (пионер в своей области) поглощалась конкурентом.


Это ты к чему? Эта тема важна для тебя? Пытаешься выдумать ветряные мельницы, чтобы было что побеждать?

Что-то я сомневаюсь, что из-за такого произошло поглощение — зачем поглотителю такой код и такие разработчики, которые такой код пишут?

LMA>>Я уже привел решение, которое я считаю нормальным — это решение, которое кандидаты дают именно за 1-2 минуты.

LMA>>a/2+b/2 дает неверный результат для двух нечетных чисел, а casting к большему — нормальный если casting происходит к большему (а не просто к long long или double).
E>Большинство людей на этом форуме считают твое решение ненормальным. Тебя еще никто не поддержал. Одни неучи в индустрии сидят, как я понимаю?

Когда нет аргументов, начинаешь оперировать фразами вроде "миллиард китайцев не может ошибаться"?

Мне все равно, сколько людей на этом форуме считают, что корректность кода не важна, или что корректность кода менее важна, чем, чтобы любой первокурсник (может еще первоклассник?) мог разобраться в коде сходу.

LMA>>Я все еще жду про UB из стандартов C/C++, с которыми ты сталкивался "когда я еще на ассемблере писал" (выделил).

E>Сложение, умножение чисел, которые близкие к максимальным значениям, что просходит переполнение. На ассемблере таким приходилось часто заниматься. На высокоуровневых языках не припомню такого.

И где при этом происходит UB? Переполнение и UB — это вещи ортогональные. Это в C/C++ ты можешь на одном и том же компиляторе получить для (a+b)/2 для a == INT_MAX и b == INT_MAX результат INT_MAX, а для a == INT_MAX и b == INT_MAX-1 отрицательную величину, а для ассемблера — ты такое не получишь.

LMA>>Если по каким-то причинам так сделать не удастся — можно и костыль использовать, но тогда сравнивать разницу нужно не с 1, а c величиной, зависящей, от a и b. Причем это именно костыль, который лечит симптом, а болезнь в том, что кто-то знал, что надо часто сравнивать результаты функции, но не включил это в требования к функции.

E>Вот это вообще жесть . Представляю что у вас там в требованиях творится, если такое надо включать. На 1 строчку кода 100 строк документации, я так понимаю? Результаты нужно ведь не только сравнивать, но и делить на них, умножать, возводить в степень и т.д. Итого — надо для каждой функции писать теперь что с результатом делать можно, а что нет ? Всегда считал, что не дело функции знать, как будет использоваться ее результат. Базовый принцип это, вообще то. Если можно результат использовать неправильно, он будет использован неправильно. И никакая кипа документации не поможет. Если этот принцип нарушать — крупную сложную систему не построить, даже на средней все рухнет.

Надо просто понимать, что является типичным поведением, а что — не типичным. И нетипичное поведение описывать в требовании. Если вызывающая часть критична к способу округления — это должно быть указано, если ей это все равно — не указывать. Программист, получив такое задание, не может знать как будет использован результат, поэтому волен использовать, что ему удобнее в рамках контракта, например, как я уже писал
Автор: LordMAD
Дата: 23.01.10
, если возвращаемое число — сумма денег, то оптимальным может быть банковское округление и любое другое — будет неверным. Функции все равно — что будут делать с результатом, а вот вызывающей стороне — не все равно, что возвращает функция, поэтому если кто-то ввел такую зависимость (от способа округления) — он должен об этом позаботится или избавится от зависимости (не сравнивать результаты вызова при различном порядке следования аргументов). F почему правильно предоставлять свободу программисту в рамках контракта — я уже приводил пример с std::max.
Re[30]: собеседование
От: elmal  
Дата: 10.02.10 13:23
Оценка:
Здравствуйте, LordMAD, Вы писали:

LMA>Ты имел один исходник на ассемблере, из которого получал программу для 4 различных процессоров? Если нет — то к чему это ты?

Бывают случаи, когда ассемблерную программу под один процессор требуется портировать на другой процессор. Принципы одинаковые. Детали — разные. Алгоритм должен быть достаточно универсальным.

LMA>Что с того, что исключения не поддерживают старые компиляторы? Если так рассуждать — надо вообще отказываться от половины C++, включая шаблоны, using и прочее.

Вот в том то и дело, что имеешь дело с разными платформами — хрен у тебя получится написать универсально. Хочешь универсальности и портируемости, K&R рулез, и то надо быть аккуратным. А на практике имеешь дело именно с конкретными платформами. Для которых можно быть достаточно уверенным, что long long > int.

LMA>А ты объясни — почему ты считаешь что из того что компилятор заточен под платформу, следует что и код заточен под платформу. Я это кроме как тем что ты пишешь код, который будет компилироваться только одним компилятором, ничем другим объяснить это не могу.

Типичный код, который я пишу, без проблем при необходимости перенесется на любой другой язык, и платформу. Практически в лоб будет этот перенос, поменять придется в основном синтаксис. UB не будет, особенно если это сложение.

LMA>Есть старая истина: the only valid measurement of code quality: WTFs/minute. Опять возвращаемся к design review и code review. Короче говоря — то о чем ты пишешь — не проблема, если бардака нет.

У меня сомнение в отсутсвии бардака, если коммутативность считается излишеством.

LMA>При каком коде?

При типичном спагетти коде основное — знание языка. При нормальном коде основное — здравый смысл + умение проектировать.

LMA>Когда нет аргументов, начинаешь оперировать фразами вроде "миллиард китайцев не может ошибаться"?

Аргументы были. Не только у меня. Напиши, как предполагается сравнивать результаты. Если функция что-то возвращает, вполне логично, что результат придется сравнивать. Я хочу узнать как мне надо сравнивать. Так как у меня впечатление, что я всю жизнь сравниваю неправильно (а я сравниваю либо через ==, либо через equals (синонимы мз разных языков не привожу), а надо как-то еще, похоже).

LMA>Мне все равно, сколько людей на этом форуме считают, что корректность кода не важна, или что корректность кода менее важна, чем, чтобы любой первокурсник (может еще первоклассник?) мог разобраться в коде сходу.

Пишешь вот такие хаки если — они должны быть протестированы сверхтщательным образом. Библиотеки все-таки. Туда лезть очень редко приходится. В принципе да, библиотека должна быть black box, туда лезть совершенно необязательно, потому код там вполне имеет право быть запутанным, если уж там надо и скорость, и переносимость. Одно но только — библиотеки не должны потенциальных багов содержать никогда! То есть должно быть крайне маловероятно, что она начнет тормозить, или что приколы при округлении получим, зависимые от порядка аргументов.

LMA>И где при этом происходит UB? Переполнение и UB — это вещи ортогональные. Это в C/C++ ты можешь на одном и том же компиляторе получить для (a+b)/2 для a == INT_MAX и b == INT_MAX результат INT_MAX, а для a == INT_MAX и b == INT_MAX-1 отрицательную величину, а для ассемблера — ты такое не получишь.

На разных ассемблерах вполне получишь. Не надо мыслить на уровне языка, надо мыслить выше. То что мнемоники разные, порядок аргументов разный, не значит, что язык разный. Можно макросами настроить все таким образом, что получим ассемблер с единым синтаксисом, вот для него UB вполне будет. А можно теми же макросами обеспечить определенное поведение. Шире надо мыслить, шире .

LMA>max(a, b) = 0 и max(b, a) = 0 дадут разные результаты при a == b. F почему правильно предоставлять свободу программисту в рамках контракта — я уже приводил пример с std::max.

Использование конечно функции достаточно экзотическое, но поведение вполне логичное будет. И тот, кто будет пользоваться этим, справедливо будет полагать, что вернется одно значение, а не 2. И проблемы это, в результате, не вызовет. В отличие от твоего решения, там поведение ну совершенно не поддается логике.
Re[31]: собеседование
От: LordMAD Россия  
Дата: 11.02.10 06:49
Оценка:
Здравствуйте, elmal, Вы писали:

LMA>>>>Грабли будут разные, потому что на том же ассемблере, поведение будет детерминированным, в отличие от C/C++, где будет UB. Соответственно при UB будет большая разница в том, как обрабатывается integer overflows в конкретной версии компилятора и на конкретной платформе и с конкретными параметрами компиляции. Соответственно, применительно к C++, приходим даже к теме гарантий безопасности исключений Абрамса. Могу конечно, предположить, что ты считаешь, что и безопасный относительно исключений код писать "на практике требуется очень и очень редко"?

E>>>Ассемблеры, они разные. И в общем случае на разных ассемблерах поведение ни черта не детерминировано тоже. Я, например, знал как минимум 4 системы команд разных процессоров. Когда знал только один процессор, для меня было все детерминировано. Когда стал знать несколько — стал мыслить более высокоуровнево.
LMA>>Ты имел один исходник на ассемблере, из которого получал программу для 4 различных процессоров? Если нет — то к чему это ты?
E>Бывают случаи, когда ассемблерную программу под один процессор требуется портировать на другой процессор. Принципы одинаковые. Детали — разные. Алгоритм должен быть достаточно универсальным.

И какое это имеет отношение к UB? И к тому "на разных ассемблерах поведение ни черта не детерминировано тоже"?

LMA>>Что с того, что исключения не поддерживают старые компиляторы? Если так рассуждать — надо вообще отказываться от половины C++, включая шаблоны, using и прочее.

E>Вот в том то и дело, что имеешь дело с разными платформами — хрен у тебя получится написать универсально.

Да ну? А мужики то и не знали!

LMA>>В тех случаях когда переносимость имеет наивысший приоритет, лучше просто использовать чистый С, причем желательно не C99, а K&R. Отказываться от исключений в C++ можно, когда речь идет о небольших автономных поделках, так например поступает google с их open-source проектиками. А вот в полноценных проектах так делать не стоит, потому что иначе придется иметь дело только с "наибольшим общим делителем" возможностей, а для систем нормальных размеров проще на новую платформу подходящий компилятор портировать или от платформы отказаться.

E>Хочешь универсальности и портируемости, K&R рулез, и то надо быть аккуратным. А на практике имеешь дело именно с конкретными платформами. Для которых можно быть достаточно уверенным, что long long > int.

То есть ILP64 и SILP64 — они такие мифические, мы на них глаза закроем, чтобы не портили идиллической картины?

LMA>>А ты объясни — почему ты считаешь что из того что компилятор заточен под платформу, следует что и код заточен под платформу. Я это кроме как тем что ты пишешь код, который будет компилироваться только одним компилятором, ничем другим объяснить это не могу.

E>Типичный код, который я пишу, без проблем при необходимости перенесется на любой другой язык, и платформу. Практически в лоб будет этот перенос, поменять придется в основном синтаксис. UB не будет, особенно если это сложение.

Опять возвращаемся к тому, что вместо 2 строк ты пишешь 100, получая при этом такой же результат. У тебя случайно зарплата от количества строк кода не зависит?

LMA>>Есть старая истина: the only valid measurement of code quality: WTFs/minute. Опять возвращаемся к design review и code review. Короче говоря — то о чем ты пишешь — не проблема, если бардака нет.

E>У меня сомнение в отсутсвии бардака, если коммутативность считается излишеством.

Ты про std::max?

E>При типичном спагетти коде основное — знание языка. При нормальном коде основное — здравый смысл + умение проектировать.


Ты не поверишь, каких результатов можно добится, если объединить здравый смысл, умение проектировать и знание языка!

E>>>Большинство людей на этом форуме считают твое решение ненормальным. Тебя еще никто не поддержал. Одни неучи в индустрии сидят, как я понимаю?

LMA>>Когда нет аргументов, начинаешь оперировать фразами вроде "миллиард китайцев не может ошибаться"?
E>Аргументы были. Не только у меня. Напиши, как предполагается сравнивать результаты. Если функция что-то возвращает, вполне логично, что результат придется сравнивать. Я хочу узнать как мне надо сравнивать.

Вменяемых аргументов я не увидел. Твой аргумент про то, что это подстрахует менеджеров — даже не смешно.
Как сравнивать — я уже написал — см. мой пост от 10.02.10 10:53.
Мы ходим по кругу.

E>Так как у меня впечатление, что я всю жизнь сравниваю неправильно (а я сравниваю либо через ==, либо через equals (синонимы мз разных языков не привожу), а надо как-то еще, похоже).


Если ты и типы с плавающей точкой сравниваешь через operator== — да, ты сравниваешь неправильно.
Я привел пример и с функцией, возвращающей температуру — если ты её результат будешь сравнивать через operator== — тоже неправильно.
Мы ходим по кругу.

LMA>>Мне все равно, сколько людей на этом форуме считают, что корректность кода не важна, или что корректность кода менее важна, чем, чтобы любой первокурсник (может еще первоклассник?) мог разобраться в коде сходу.

E>Пишешь вот такие хаки если — они должны быть протестированы сверхтщательным образом. Библиотеки все-таки. Туда лезть очень редко приходится. В принципе да, библиотека должна быть black box, туда лезть совершенно необязательно, потому код там вполне имеет право быть запутанным, если уж там надо и скорость, и переносимость. Одно но только — библиотеки не должны потенциальных багов содержать никогда! То есть должно быть крайне маловероятно, что она начнет тормозить, или что приколы при округлении получим, зависимые от порядка аргументов.

Какая к черту библиотека? Мы обсуждаем задание на собеседовании!

E>>>>>Последний раз, когда мне приходилось помнить про UB, было еще тогда, когда я еще на ассемблере писал.

LMA>>И где при этом происходит UB? Переполнение и UB — это вещи ортогональные. Это в C/C++ ты можешь на одном и том же компиляторе получить для (a+b)/2 для a == INT_MAX и b == INT_MAX результат INT_MAX, а для a == INT_MAX и b == INT_MAX-1 отрицательную величину, а для ассемблера — ты такое не получишь.
E>На разных ассемблерах вполне получишь. Не надо мыслить на уровне языка, надо мыслить выше. То что мнемоники разные, порядок аргументов разный, не значит, что язык разный. Можно макросами настроить все таким образом, что получим ассемблер с единым синтаксисом, вот для него UB вполне будет. А можно теми же макросами обеспечить определенное поведение. Шире надо мыслить, шире .

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

LMA>>max(a, b) = 0 и max(b, a) = 0 дадут разные результаты при a == b. F почему правильно предоставлять свободу программисту в рамках контракта — я уже приводил пример с std::max.

E>Использование конечно функции достаточно экзотическое, но поведение вполне логичное будет. И тот, кто будет пользоваться этим, справедливо будет полагать, что вернется одно значение, а не 2. И проблемы это, в результате, не вызовет. В отличие от твоего решения, там поведение ну совершенно не поддается логике.

Так в чем разница?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.