Вопросы по JavaScript и C#, которые неожиданно вызывают затруднения на собеседованиях

85 комментариев
Вопросы по JavaScript и C#, которые неожиданно вызывают затруднения на собеседованиях

За последние полгода наша команда провела более сорока технических интервью с кандидатами на позиции front-end разработчика (JavaScript/CSS/ASP.NET MVC) и .NET-разработчика (С#/WPF). Мы не используем тесты и тестовые задания, а просим написать несколько строчек кода и найти ошибку в выражении. Такая методика позволяет оценить не только память, но и мышление, способности к поиску альтернативных решений и "техническое чутьё" всего за полтора часа.

В данной статье мы собрали задания, которые вызывают сложности у кандидатов разного уровня подготовки. Давайте посмотрим, какими знаниями нужно обладать, чтобы успешно пройти собеседование на должность front-end разработчика или программиста .NET в Минском офисе компании IHS.

Вопросы по JavaScript и С#/.NET

JavaScript

Наше интервью по JavaScript не проходит без вопросов о типах. Например:

1. Можно ли записать такие выражения на JavaScript? Если да, то какое значение будет у переменной a?

var a = +!!{};
var a = -![];

2. Какие значения относят к значениям falsy?

3. Чем отличается null от undefined?

4. Чему равна переменная а и какого она типа?

var a = 2 + "2";

5. Покажется ли диалоговое окно?

var a = "";
if (a != 0)
{
	alert(a);
}

А если так?

var a = "";
if (a !== 0)
{
	alert(a);
}

На самом деле можно придумать ещё много подобных вопросов, целью которых является проверка знаний особенностей типов и их приведения в JavaScript. Чтобы ответить успешно на все вопросы о типах в JavaScript нужно знать следующее. 

JavaScript – это интерпретируемый язык программирования c динамической типизацией и автоматическим управлением памятью. Свойство динамической типизации языка означает то, что переменной одного типа можно присвоить значение другого типа (в отличие от языков статической типизации – С++, С#, Java). Переменные всегда имеют конкретный тип, который определяется оператором typeof.

Встроенные типы значений в JavaScript (источник)

Тип Описание
number Числовой тип c плавающей запятой, 8 байт, аналог double (источник)
boolean Булев тип, содержит только 2 значения: true и false
string Строковый тип, символ занимает 2 байта, кодировка UTF-16 (источник)
object Любой встроенный или пользовательский объект, включая массив и объект даты
function Любой объект функции
undefined Специальное значение для неинициализированной переменной

Сравните значения, возвращаемые этим оператором, в консольном примере, запущенном на Node.js. 

var a;
console.log(typeof(a));
a = "String value";
console.log(typeof(a));
a = 5;
console.log(typeof(a));
a = false;
console.log(typeof(a));
a = function() { };
console.log(typeof(a));
a = {};
console.log(typeof(a));
e:\Articles>node .\typeof.js
undefined
string
number
boolean
function
object

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

Помимо типов в JavaScript существует понятие truthy и falsy значений (подробнее во второй главе книги "Object-Oriented JavaScript" Стояна Стефанова). Они примечательны тем, что в условиях конструкций if-elsefor, и while значения truthy ведут себя как значение true булева типа, а значения falsy – как значение false булева типа.

К значениям falsy относятся значения, перечисленные ниже.

Falsy значение Описание
"" или '' Пустая строка, тип string
0 Ноль, тип number
null Переменная, инициализированная пустым значением, тип object
undefined Неинициализированная переменная, тип undefined
false Само значение false типа boolean
NaN Нечисло, тип number

К значениям truthy относятся все остальные.

Значения falsy ведут себя как false булева типа и в операциях нестрогого сравнения (== и !=, но только при сравнении между false, 0 и пустой строкой).

Введя понятия truthy и falsy, можно рассмотреть операцию приведения к типу boolean. Для этого существует оператор отрицания: ! – одинарное отрицание, !! – двойное отрицание.

Одинарное отрицание (!) приводит значение truthy к false, а значение falsy к true.

Двойное отрицание (!!) приводит значение truthy к true, а значение falsy к false.

На Node.js все вышесказанное выглядит следующим образом.

console.log("!false = " + (!false));
console.log("!true = " + (!true));
console.log("!{} = " + (!{}));
console.log("![] = " + (![]));
console.log("!0 = " + (!0));
console.log("!null = " + (!null));
console.log('!function(){}='+(!function(){}));
console.log("!'' = " + (!''));
console.log("!'a' = " + (!'a'));
console.log("!'NaN' = " + (!(0/0)));
console.log("!undefined = " + (!void(0)));

console.log("!!false = " + (!!false));
console.log("!!true = " + (!!true));
console.log("!!{} = " + (!!{}));
console.log("!![] = " + (!![]));
console.log("!!0 = " + (!!0));
console.log("!!null = " + (!!null));
console.log('!!function(){}='+(!!function(){}));
console.log("!!'' = " + (!!''));
console.log("!!'a' = " + (!!'a'));
console.log("!!'NaN' = " + (!!(0/0)));
console.log("!!undefined = " + (!!void(0)));
e:\Articles\node .\boolean.js
!false = true
!true = false
!{} = false
![] = false
!0 = true
!null = true
!function() {} = false
!'' = true
!'a' = false
!'NaN' = true
!undefined = true
!!false = false
!!true = true
!!{} = true
!![] = true
!!0 = false
!!null = false
!!function() {} = true
!!'' = false
!!'a' = true
!!'NaN' = false
!!undefined = false

В JavaScript есть два оператора сложения (+): унарный и бинарный. Унарный + требует лишь один операнд и выполняет приведение типа к числу. Бинарный + служит для конкатенации строк, если хотя бы один операнд не является числом или булевым значением, или для сложения чисел, если оба операнда типа number или boolean.

Правило работы унарного оператора + (подробнее): значение falsy приводится к 0 типа number, значение truthy кроме строк приводится к нечислу (NaN) типа number, строка, содержащая число, приводится к этому числу типа number, любая другая строка даёт в результате нечисло (NaN) типа number, значение true приводится к 1.

console.log("+0 = " + (+0));
console.log("+false = " + (+false));
console.log("+true = " + (+true));
console.log("+{} = " + (+{}));
console.log("+[] = " + (+[]));
console.log("+[1,2,3] = " + (+[1,2,3]));
console.log("+'' = " + (+''));
console.log("+NaN = " + (+(0 / 0)));
console.log("+null = " + (+null));
console.log("+undefined = " + (+void(0)));
console.log("+'45' = " + (+'45'));
console.log("+'a' = " + (+'a'));
console.log("+'45a' = " + (+'45a'));
console.log("+'a45' = " + (+'a45'));
e:\Articles>node .\number.js
+0 = 0
+false = 0
+true = 1
+{} = NaN
+[] = 0
+[1,2,3] = NaN
+'' = 0
+NaN = NaN
+null = 0
+undefined = NaN
+'45' = 45
+'a' = NaN
+'45a' = NaN
+'a45' = NaN

Обращаем внимание, что значение undefined приводится к нечислу (NaN) по спецификации (источник). Обращаем также внимание на то, что приведение пустого массива к типу number даёт 0. Это из-за внутренней реализации метода DefaultValue массива, который возвращает для пустого массива пустую строку, а для массива с одним элементом – значение этого элемента (источник).

Помимо унарного оператора + в JavaScript имеется и унарный минус (-), действие которого аналогично унарному оператору + с той лишь разницей, что результат операции приведения типа является отрицательным числом (подробнее).

Бинарный оператор + переходит в режим конкатенации строк, если хотя бы один операнд не является числом или булевым значением. Приведение операнда к строке выполняется через вызов метода toString.

Если бинарный + применяется к числу и логическому значению, то последнее приводится к типу number. То же самое происходит и при сложении двух логических значений, поэтому true + true === 2.

Теперь дать ответы на вопросы, заданные в начале раздела, не составляет труда:

1. Результат первого выражения – число 1, второго – 0 (вернее 0 с минусом, что соответствует спецификации).

2. Согласно Стояну Стефанову: false, null, undefined, NaN, "" (пустая строка) и 0.

3. Типом и назначением.

4. Строка "22".

5. В первом случае диалог не покажется, т.к. при нестрогом сравнении пустая строка признаётся равной нулю. То же самое верно и при нестрогом сравнении с false, но неверно при сравнении с null, undefined и NaN (нечисло не равно даже самому себе).

С#/.NET

Трудно представить приложение, в котором не требуется работа со строками. Интернирование и неизменность строк в среде .NET является избитой темой, однако практика показывает, что не все кандидаты имеют чёткое представление об этих свойствах. Нужно пояснить, что интернирование строк встречается не только в .NET, но и в Java, а также других средах программирования (подробнее). Давайте разберёмся, что необходимо знать, чтобы легко ответить на следующие вопросы:

1. Почему строки в .NET являются неизменяемыми объектами (immutable)?

2. Что такое интернирование строк в .NET и можно ли отключить это поведение?

3. Почему для конкатенации строк лучше использовать StringBuilder, а не String.Concat?

Интернирование строк – это метод организации экземпляров строк в памяти выполняемого приложения, при котором для каждого строкового значения создается (или хранится) только один объект строки.

В следующем примере двум переменным присваивается одно и то же строковое значение. Если мы запустим этот код на выполнение, то увидим, что обе переменные указывают на один и тот же объект в памяти.

class Program
{
    static void Main(string[] args)
    {
        var a = "test string";
        var b = "test string";            
        // выводит True
        Console.WriteLine("Строковые литералы интернированы: " + ReferenceEquals(a, b));
    }
}

Структура данных для хранения интернированных строк называется Intern Pool.

По умолчанию все литеральные строки в .NET интернированы, а строки, создаваемые динамически, – нет. Однако в классе System.String есть статический метод Intern, который позволяет поместить объект строки в Intern Pool, если строка ещё не интернирована, и вернуть ссылку на интернированный объект (подробнее).

Основные преимущества интернированных строк: уменьшение объёма памяти для строковых объектов и увеличение производительности операций сравнения. Методы Equals класса System.String сначала проверяют равенство строк по ссылке, а затем – по значению.

Реализация метода Equals, дизассемблированного ILSpy

public static bool Equals(string a, string b)
{
    return a == b || (a != null && b != null && a.Length == b.Length && string.EqualsHelper(a, b));
}

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

class Program
{
    static void Main(string[] args)
    {
        var s1 = new string(new[] { 't','e','s','t',' ','s','t','r','i','n','g' });
        var s2 = string.Join(" ", new[] { "test", "string" });

        Console.WriteLine(ReferenceEquals(s1, s2));

        var s1Interned = string.Intern(
            new string(new [] { 't','e','s','t',' ','s','t','r','i','n','g' }));

        var s2Interned = string.Intern(string.Join(" ", new [] { "test", "string" }));

        Console.WriteLine(ReferenceEquals(s1Interned, s2Interned));
        
        var n = 10000000;
        var sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < n; i++)
        {
            var res = s1 == s2;
        }
        sw.Stop();
        Console.WriteLine("Сравнение неинтернированных: " + sw.ElapsedMilliseconds);
        sw.Reset();
        sw.Start();
        for (int i = 0; i < n; i++)
        {
            var res = s1Interned == s2Interned;
        }
        sw.Stop();
        Console.WriteLine("Сравнение интернированных: " + sw.ElapsedMilliseconds);
        sw.Reset();

        sw.Start();
        for (int i = 0; i < n; i++)
        {
            switch (s1)
            {
                case "test string": break;
            }
        }
        sw.Stop();
        Console.WriteLine("Сравнение неинтернированных [switch]: " + sw.ElapsedMilliseconds);
        sw.Reset();
        sw.Start();
        for (int i = 0; i < n; i++)
        {
            switch (s1Interned)
            {
                case "test string": break;
            }
        }
        sw.Stop();
        Console.WriteLine("Сравнение интернированных [switch]: " + sw.ElapsedMilliseconds);

        Console.ReadKey();
    }
}

Полученный результат:

False
True
Сравнение неинтернированных: 144
Сравнение интернированных: 48
Сравнение неинтернированных [switch]: 148
Сравнение интернированных [switch]: 56

Вывод: если в памяти необходимо хранить большой объём строковых данных с повторяющимися значениями для последующего поиска (кэш), то имеет смысл работать именно с интернированными строками.

Стоит отметить, что в .NET интернирование строк реализовано в пределах домена приложения.

Реализация метода Intern, дизассемблированного ILSpy

public static string Intern(string str)
{
    return Thread.GetDomain().GetOrInternString(str);
}

Чтобы интернирование было возможно, строка должна быть неизменной (immutable). Это значит, что любая операция, модифицирующая значение строки, порождает новый экземпляр класса System.String, совершенно не затрагивая существующий. Однако это не эффективно при частых операциях объединения и замещения частей строк, т.к. приводит к созданию слишком большого числа экземпляров класса System.String, которые содержат промежуточные строковые значения. Для решения этой проблемы служит класс StringBuilder. Принцип его работы прост: исходная строка преобразуется в массив символов, далее все операции по изменению значений производятся уже над массивом символов. Для получения результирующей строки используется метод ToString, который вначале выделяет необходимую память, а затем посимвольно копирует массив с помощью внутреннего метода String.wstrcpy по новому адресу. StringBuilder используется внутри метода String.Join.

Оператор сложения строк + аналогичен String.Concat. С помощью ILDasm можно убедиться, что они компилируются в один и тот же IL-код.

class Program
{
  static void Main(string[] args)
  {
    string s1 = "test";
    string s2 = "string";
    string s = s1 + s2;
  }
}

 

class Program
{
  static void Main(string[] args)
  {
    string s1 = "test";
    string s2 = "string";
    string s = string.Concat(s1, s2);
  }
}

 

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       21 (0x15)
  .maxstack  2
  .locals init ([0] string s1,
           [1] string s2)
  IL_0000:  ldstr      "test"
  IL_0005:  stloc.0
  IL_0006:  ldstr      "string"
  IL_000b:  stloc.1
  IL_000c:  ldloc.0
  IL_000d:  ldloc.1
  IL_000e:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
  IL_0013:  pop
  IL_0014:  ret
} // end of method Program::Main

Вывод: для объединения множества строк нужно использовать StringBuilder или String.Join, для выполнения множества операций замещения частей строки нужно использовать StringBuilder.Replace, а не String.Replace.

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

Если у Вас спрашивают, как отключить интернирование строк в .NET, то логичным является встречный вопрос: зачем? Интернирование строковых литералов никому не мешает, а динамические строки по умолчанию не интернированы.

Заключение

Мы привели примеры вопросов по .NET, которые проверяют знания в областях, понимание которых необходимо для решения задач построения нагруженных систем, работающих с большими объёмами данных. Акцент здесь делается не только на владении технологиями, но и на понимании того, как они реализованы. Такие знания требуются для повышения качества и оптимизации продукта, а также для поиска альтернативных архитектурных решений.

Знание особенностей типов и их приведения в JavaScript позволяет создавать лаконичный и эффективный код. Пример: функция isNumeric в jQuery:

isNumeric: function( obj ) {
  // parseFloat NaNs numeric-cast false positives (null|true|false|"")
  // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  // subtraction forces infinities to NaN
  // adding 1 corrects loss of precision from parseFloat (#15100)
  return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
},

Другим отличным примером является функция, которую можно использовать для форматирования даты (первая глава книги Test-Driven JavaScript Development):

function zeroPad(num) {
  return (+num < 10 ? "0" : "") + num;
}

На сегодня всё. Хотелось бы узнать мнение читателей о необходимости делиться подобными материалами.

Хотите сообщить важную новость?

Пишите в наш Телеграм

Читайте также

Вакансии для Android-разработчиков на jobs.dev.by
Вакансии для Android-разработчиков на jobs.dev.by
Вакансии для Android-разработчиков на jobs.dev.by
Отпустило: большинство уже не боится остаться без работы и хорошей зарплаты
Отпустило: большинство уже не боится остаться без работы и хорошей зарплаты
Отпустило: большинство уже не боится остаться без работы и хорошей зарплаты
Больше 50% белорусских айтишников не боятся остаться без работы или устраивающей зарплаты. Лишь меньше 10% ИТ-специалистов опасаются увольнения. Таковы результаты кризисного опроса dev.by по итогам июня. Итоги майского опроса про настроения и перспективы — здесь.
7 комментариев
Известная эйчар найдёт работу диджеям, которые включили «Перемен» на госпразднике
Известная эйчар найдёт работу диджеям, которые включили «Перемен» на госпразднике
Известная эйчар найдёт работу диджеям, которые включили «Перемен» на госпразднике
12 комментариев
Вакансии для iOS-разработчиков на jobs.dev.by
Вакансии для iOS-разработчиков на jobs.dev.by
Вакансии для iOS-разработчиков на jobs.dev.by

Обсуждение

0

Вначале йаньдекс публикует статью "как правильно пройти у нас собеседование?", теперь вот еще одна контора. Это типа такой модный тренд что-ли? Никто что-ли собеседование вообще не проходит без шпаргалок?! :)

Для кого это? Зачем это? Чего достичь желаем?

1

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

13

Оно не поднимает _уровень_ знаний и образования, оно просто увеличивает количество знаний. В целом абсолютно бесполезных для профессиональной программерской деятельности :)

Для неявно-типизированного языка типа жабаскрипт такие примеры неявных преобразований (и, типа, техник) можно генерить мегабайтами. И что? Умения написать быстрый, простой, понятный, читабельный и легко модифицируемый даже пионэром Васей код, знание всей этой жести ни разу не прибавит. Скорее убавит.

2

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

1

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

1

Экземпляр полезной статьи, которых, к сожалению, совсем не много на dev.by.

8

данная статья это как описание садомазо в книжке по половому воспитанию детей.

1

Я вот хочу сказать, что это яркий пример бесполезной статьи. Какую практическую пользу носит в три раза быстрее? За частую мне все равно выполнится операция сравнения строк за 0.00003 секунды или за 0.00001. В реальном мире где основное время уходит на сетевой выхов или обращение к диску сравнение строк, которые находятся в памяти, выполняется рочти моментально.

Я бы руки отрезал тем кто в js пишет fusy логику построенную на специфике языка. Код получается лаконичный но не читаемый

6

>> Знание особенностей типов и их приведения в JavaScript позволяет создавать лаконичный и эффективный код

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

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

6

Я собеседовал около 50 человек и сам собеседовался приблизительно в 30 конторах и нахожу предложенные вопросы крайне посредственными.

По жаваскрипту 3-й и с натяжкой 2-й вопрос норм. Остальные - из разряда «давай я покажу тебе код, который никогда не стоит писать, а ты мне расскажешь, как он работает».

Вопросы по строкам в .NET в печёнках уже сидят по той причине, что объём внимания, уделяемый строкам на собеседовании, абсолютно непропорционален количеству проблем, которые возникают при работе со строками в реальных приложениях. Например, с интернированием строк я знаком только «на бумаге» хотя уже не первый год работаю. Более того, тестирование производительности сравнения показывает, что пляски с интернированием улучшат производительность на константу, что ставит практичность вопроса на уровень вопросов

«Как чуть-чуть улучшить производительность .NET-приложения?» Ответ: переписать часть кода на ассемблере.

Или

«Почему цикл for (var i=0; i < count; i++) выполняется медленнее, чем for (var i = count-1; i>=0; i--)»?

Вместо интернирования лучше бы спросили, как работает Dictionary.

Андрей Митин
Андрей Митин System analyst в CTDEV
2

Про интернирование - абсолютно согласен. Читал когда-то статью о сравнении билдера, склейки и формата. Там было убедительно показано и подкреплено тестами, что проблема эта раздута (в основном из-за фреймворка 1.1), и на практике следует прибегать ровно к тому методу, который больше соответствует ситуации и лучше читается. Тянешь шаблон строки из внешнего ресурса и подставляешь данные? - используй формат (хотя я лично предпочитаю заменять риплэйсом именованные параметры типа {LastName}, а не путаться в безымянных {0}...{999}). Собираешь в цикле Очень Длинную Строку? - билдер в помощь. Для остального нет ничего прозрачней, чем "User " + username + " wrote " + numberOfComments + " comments".

4

Я бы немного переделал в статье пару фраз:
JavaScript – это интерпретируемый язык программирования c динамической типизацией и автоматическим управлением памятью. Свойство динамической типизации языка означает то, ... "можно задавать на собеседование такие запутанные задачи на знание фич динамической типизации и скрытых преобразований типов.".
Надеюсь те, кто задают такие задачи получат гору такого гавнокода в свои проекты, вы их заслуживаете...

"переменной одного типа можно присвоить значение другого типа (в отличие от языков статической типизации – С++, С#, Java)"
Шэф в JavaScript переменные никакого типа. Это просто переменные. Что положишь, то там и лежит.

4

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

Anonymous
Anonymous Старший разработчик в Adform BY
-1

Тип переменной определяется значением, иначе - тип undefined (http://msdn.microsoft.com/en-us/library/ie/67defydd(v=vs.94).aspx)
"JavaScript variables have no predetermined type. Instead, the type of a variable is the type of its value."

0

"На сегодня всё. Хотелось бы узнать мнение читателей о необходимости делиться подобными материалами."

Если вам нечего больше спросить на собеседовании кроме этого, это печально. Могу порекомендовать хотя бы этот список
https://github.com/darcyclarke/Front-end-Developer-Interview-Questions/blob/master/Translations/Russian/README_RU.md
так хотя бы адекватно можно оценить понимание работы браузера, чтения и исполнения кода и прочее.

0

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

2

Такие вопросы вызывают всегда затруднения, это вопросы из области проблем любого уровня знания js, потому что в реальных проектах к этим областям никогда не обращаются. Я не говорю конкретно про эти примитивные примеры, есть много других разнообразных вариантов, которые никто не ответит на все 100.

0

"Свойство динамической типизации языка означает то, что переменной одного типа можно присвоить значение другого типа".
То, что вы называете динамической типизацией вообще вроде как называется слабой типизацией (когда при таких вот присваиваниях происходят неявные, "автоматические" преобразования типов). А динамическая типизация означает, что тип некой переменной определяется непосредственно в runtime, в отличие от статической, когда это происходит на этапе компиляции. http://habrahabr.ru/post/161205/

Anonymous
Anonymous Старший разработчик в Adform BY
1

Пример свойства динамической типизации (http://en.wikipedia.org/wiki/Javascript#Dynamic):
var a = "string";
a = 5; // переменная а уже указывает на значение другого типа, тип определяется во время выполнения

Пример свойства слабой типизации:
var a = 5 + "6"; // неявная конвертация числа 5 в строку (http://en.wikipedia.org/wiki/Strong_and_weak_typing)

Будьте внимательнее, тут нет противоречия.

0

Согласен, не так понял вас. Был бы код в статье - вопросов бы не было.

drew
drew ведущий инженер-программист в SCAND
0

Надо ли делиться подобными материалами? Однозначно надо. Кто-то что-то полезное узнает из статьи. А кто-то - из комментов, которые непременно будут гневными :)
О полезности таких вопросов на собеседованиях - сомнительно. Я считаю, что способность ответить или не ответить на все вопросы почти никак не характеризует соискателя.

P.S. Читал о javascript, .net пропустил.

Андрей Митин
Андрей Митин System analyst в CTDEV
1

Довольно провокационные примеры конечно. Зачем, если больше половины кандидатов получается отсеять, просто попросив составить таблицы истинности для &, | и ^?

0

собеседую джуниоров на sql.
Вопрос: как найти неуникальные значения в одном столбце? Решает. group by having...
А в двух ? Не знает.
И так почти каждый второй.
Это вот почему?? Я не понимаю.

amok
amok Team Lead в Ergalio
1

Со StringBuilder нужно осторожнее. Там внутренний буфер в два раза каждый раз увеличивается, если его не задать. При попытке создасть строку на 500мб он попробует выделить непрерывный кусок памяти на 1гб и получит OutOfMemory.

У половины кандидатов вызывает ступор вопрос по SQL, что будет:
select * from T1,T2

0

в чем практический смысл данного запроса ?

amok
amok Team Lead в Ergalio
0

Выяснить, знает ли человек про декартово произведение.

0

декартово произведение может и знать, без относительно к скл.

0

Спросили бы тогда уже почему реляционные базы данных называются так (имею в виду понятие "реляционные")

amok
amok Team Lead в Ergalio
0

Если же нужен практический смысл. Скажем, нужно вам отчёт сделать по каждому месяцу за последние 5 лет по продажам, а данные есть не за каждый месяц...

0

поразительно то, что в Жаве есть схожая проблема со стринг буфером :) правда уже не слежу за перепитиями различных ЖДК версий и их влияние на внутренние нюансы имплементации, возможно это уже не 100 процентов так. со временем пришел к выводу что тригером к подобного рода знаниям "унутранных справ" является плохой код.

amok
amok Team Lead в Ergalio
0

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

2

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

0

если кандидату зададут пачку таких вопросов, он может сказать "Я отказываюсь отвечать по вопросам не поддерживаемого кода составленного из анти-паттернов" ? Как это охарактеризует соискателя?

0

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

for(i=0; i< m ; i++)
for(k in obj) ...

Anonymous
Anonymous
0

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

1

Гм. Ну а какие вопросы вы задаете? Ведь есть масса товарищей, которые очень умело рассказывают о своем опыте, даже расскажут архитектурные решения, паттерны. Могут ответить на вопросы из реальной жизни проекта. По sql расскажут как все устроено и работает, зачем нужны индексы и т.п. А потом смотришь через 3 месяца его код - а там 14 вложенных подзапросов в sql, 7 вложенных форов в c#, инлайновый хаотичный javascript в разметке.
Я считаю, что эти вопросы можно задавать, но только тем, кто уже прошел стадию стандартных вопросов успешно. Можно выразиться, что это вопросы со звездочкой. Просто так. Интереса ради.
Могу согласиться, что слово "неожиданно" из темы поста можно смело убирать.

Anonymous
Anonymous
1

После стандартных про "паттерны и SQL" на мой взгляд "со звездочкой" вопросы нужно задавать по теме задач, под которые девелопер берется на работу. Если задавать "вопросы со звездочкой" а-ля приведенных выше, какая от них польза на проекте? Да никакой.

1

ИМХО проще товарища научить правильно кодить, чем правильно мыслить. Поэтому если товарищ хорошо ориентируется в паттернах и знает как там внутри все устроено - да и черт бы с ним, сколько у него в коде вложеных подзапросов. Лично я это замечу не через три месяца, а в тот же день после ревизии кода новичка и скорректирую согласно той нотации, какой принято придерживаться на конкретном проекте.

1

Какие образом понимание работы такого жаваскрипта

var a = +!!{};
var a = -![];

уберегает от "14 вложенных подзапросов в sql, 7 вложенных форов в c#, инлайновый хаотичный javascript в разметке"? Может, лучше дать небольшое тестовое задание и по нему смотреть, устраивает код или нет? Ну или хотя бы SOLID спросить или предложить оценить качество стороннего кода.

Алексей Данченко
Алексей Данченко Инженер-программист в ЛюксСофт
2

>предложить оценить качество стороннего кода

А для сильных духом собеседователей дать свой собственный код на оценку кандидату :)

0

Отличный вариант! Но при этом конечно надо писать всегда нормальный код, чтоб не стыдно было показать в любой момент )

0

Я такое однажды предлагала в обсуждении какой-то конторы, рьяно требующей примеры кода от кандидатов. Они не оценили и заминусовали комментарий :D

drew
drew ведущий инженер-программист в SCAND
1

Иногда минусы - тоже показатель того, что говоришь правильные вещи :)

1

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

Anonymous
Anonymous Старший разработчик в Adform BY
-1

Библиотека jQuery - реальный проект или нет? Разработчики jQuery тоже самоутверждаются?

Метод isNumeric (https://github.com/jquery/jquery/blob/master/src/core.js)
Метод dataAttr (https://github.com/jquery/jquery/blob/master/src/data.js)

0

как я понимаю c точки зрения жквери строка типа "1" будет считаться нумерик !?

Anonymous
Anonymous Старший разработчик в Adform BY
-1

Нет, "1" - всегда строка. Привести к числу (тип number) можно 2-мя способами:
1. var a = parseInt("1", 10); // Обязательно указывается второй параметр - десятичная сс
2. var a = +"1"; // a === 1 -> true

Однако, parseInt("1 some text", 10) тоже вернет число 1, а +"1 some text" - NaN.

0

я говорю о том как работает метод жкверей isNumeric, а не о том как нужно это делать. часть условия метода isNumeric ((obj - parseFloat( obj ) + 1) >= 0) распознает строки как числа. obj = "1" это у них нумерик. отсыл на жквери оказалась не показательным, скорее наоборот :)

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

Anonymous
Anonymous Старший разработчик в Adform BY
-1

Эм... скорее не понял вопроса. "...будет считаться нумерик" я понял как "будет считаться типа number". Если Вы от том, что isNumeric("1") === true, то да, так и есть. Этот метод определяет, что аргумент может быть приведен к типу number, но не является бесконечностью или нечислом.

0

typeof ('1' * 1) // "number"
typeof ('1' / 1) // "number"
typeof (parseFloat('1')) // "number"
typeof (Number('1')) // "number"

0

Вы разрабатываете jQuery? Если да, то беру свои слова обратно - такие вопросы вызваны суровой необходимостью реализации isNumeric. Но мне кажется, что не пишете...

Anonymous
Anonymous Старший разработчик в Adform BY
0

Мы разрабатываем свой JS MVC фреймворк. На нем базируются современные продукты компании:

IHS Goldfire (http://www.ihs.com/products/design/software-methods/goldfire/index.aspx)
IHS Knowledge Collections (http://www.ihs.com/products/design/software-methods/knowledge-collections.aspx)

Мы отказались от использования существующих инструментов, например Angular JS или Dojo, чтобы ни от кого не зависеть.

Андрей Митин
Андрей Митин System analyst в CTDEV
3

Чтобы ни от кого не зависеть? Да, в каждом стороннем фреймворке есть как минимум один http://lurkmore.to/Фатальный_недостаток

3

что-то обе ваши ссылки при кликах на link-и меняют location. какой же это JS MVC ?
Отказываясь от стороннего фреймворка как Angular, становишься не менее зависим от специалистов которые его разрабатывали. Задавали ли вы себе такие вопросы ?:
- если уволятся разработчики фреймворка, как это отразится на развитии и производительности вашего фреймворка. Гугл бы не уволился...
- а если возникнут проблемы с квалифицированными кадрами, как поддерживать фреймворк ?
- не скажется ли наличие вашего фреймворка на проекте на интерес к вашим вакансиям у соискателей?

Над развитием каждого самописного фреймворка трудится не большая команда разработчиков, Angular же продвигает огромное сообщество + Google. Можно наперед сказать у какого фреймворка большие перспективы.

Anonymous
Anonymous Старший разработчик в Adform BY
-1

http://www.ihs.com - официальный сайт компании, по ссылкам доступно лишь описание продуктов IHS Goldfire и IHS Knowledge Collections, которые закрыты для общего доступа. Вот еще ссылка, уже к картинками http://www.ihs.com/pdfs/IHS-Goldfire-Cloud-Data-Sheet.pdf.

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

0

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

Anonymous
Anonymous Старший разработчик в Adform BY
0

Многие современные JavaScript фреймворки очень похожи и используют одни и те же паттерны: AMD, promise, MVC, DI, module, mixin, UT на основе JsTestDriver или jsUnit. Поэтому понять, как работает конкретный фреймворк, зная общепринятые паттерны в JavaScript, не составит труда.

0

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

2

Изобретаете велосипед?

Anonymous
Anonymous Старший разработчик в Adform BY
-2

Получается так. Ext JS слишком сложный, Dojo слишком нестабильный, AngularJS разрабатывается конкурентом, WinJS 2 года назад еще не было, CanJS только отделился от JavaScriptMVC и судьба последнего была не ясна, EmberJS был еще молод.

3

IHS позиционирует себя конкурентом Google? Как понимать ваше высказывание?
Google настолько крупный игрок, что уже определяет развитие не только своего фреймворка, но и html5. В чем конкретно они с вами конкурируют?

Не использовать бесплатный современный продукт высокого качества это как "назло маме отморожу себе уши".

Anonymous
Anonymous Старший разработчик в Adform BY
-2

С Google IHS потенциально конкурирует в области семантического поиска (http://en.wikipedia.org/wiki/Semantic_search). Однако пока Google сосредоточен на интернете, а IHS - на корпоративном сегменте. Поэтому наши рынки, насколько мне известно, не пересекаются.

А вот, например, с Thomson Reuters IHS конкурирует в области предоставления экономической информации и аналитических инструментов. Thomson Reuters - это прямой конкурент IHS (http://finance.yahoo.com/q/co?s=ihs).

Anonymous
Anonymous
1

"С Google IHS потенциально конкурирует в области семантического поиска"
Нехило по вам HR прошлись. А гугль то знает, что у него под боком такой конкурент подрастает?

Anonymous
Anonymous Старший разработчик в Adform BY
1

"В 2000 году мы встречались с представителями Google. Они посмотрели на нашу работу и сказали, что мы слишком амбициозны."

"Тот же Google в марте прошлого года объявил о замене поисковых алгоритмов, а мы все эти фичи делали еще в 2007-м. Но мы работаем на enterprise-рынке, то есть для предприятий, а они оттуда ушли."

http://dev.by/blogs/main/maksim-rastopchuk-a-pochemu-by-nam-ne-nachat-hvalitsya-esli-est-chem

Андрей Митин
Андрей Митин System analyst в CTDEV
3

jQuery - вопрос совершенно отдельный. "Странный" код вполне сгодится, если он, во-первых, скрыт за понятным названием в чёрном ящичке, а, во-вторых, необходимость делать его "странным" продиктована суровой оптимизацией (как по скорости, так и по размеру файла фреймворка), и при этом код тысячи раз оттестирован и часто меняться не собирается.
Писать же в подобном стиле прямо inline - не комильфо.

2

К одной строчке метода isNumeric настрочили 4 строки комментария - наверное не просто так, да?

И да, не стоит сравнивать уровень людей, которые разрабатывают jQuery, со средним уровнем местных жаваскрипт-программистов.

1

Я еще помню сайт с примерами такого нелогичного Javascript кода: http://wtfjs.com/

2

Я бы предложил соискателю посмотреть на распечатанный пример кода с сайта http://www.govnokod.ru/javascript и прокомментировать очевидные минусы и недочеты. Это лучше покажет как разработчик мыслит и ориентируется, чем вопрос
каков результат выражения +!!{} ? и т.п.

1

О-о-о, как там на плюсах феерично... спасибо за линку, не зналд :)

1

1. Почему строки в .NET являются неизменяемыми объектами (immutable)?

http://habrahabr.ru/post/172627/
в итоге вопрос стоит неправильно, строки при желании можно и поменять, это в Java строки сугубо immutable

2. Что такое интернирование строк в .NET и можно ли отключить это поведение?
http://habrahabr.ru/post/165729/
я бы поставил вопрос по другому: по версии дотнета свангуйте дефолтное поведение string str1 = String.Empty, интернируются или нет?
как раз будет хорошо в контексте остальных вопросов.

3. Почему для конкатенации строк лучше использовать StringBuilder, а не String.Concat?

А действительно ли это так?
http://habrahabr.ru/post/220921/
String.Concat VS StringBuilder.Append

Но едва ли мы получим в данной ситуации преимущества от использования StringBuilder. Помимо того, что код стал менее читабельным, он стал еще и менее эффективным, поскольку реализация метода Concat вычисляет длину результирующей строки и выделяет память только один раз, в отличие от StringBuilder-a который ничего не знает о длине результирующей строки.

p.s. сам занимаюсь java, но как-то от ваших вопросов попахивает не очень хорошо, так как с такими вопросами нормальный c# программист может затроллить собеседующего, а уж получить после этого офер думаю ему мечтать не следует.

Anonymous
Anonymous Старший разработчик в Adform BY
0

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

StringBuilder складывает несколько строк на 25-30% быстрее, чем String.Concat, если экземпляр StringBuilder уже создан. Если каждый раз для сложения малого числа строк создавать новый экземпляр StringBuilder, например в теле цикла, то тут я с Вами согласен - будет работать медленнее, чем Concat.

var n = 10000000;
var sb = new StringBuilder();
for (var i = 0; i < n; i++)
{
var s = sb.Append(usr).Append(name).Append(wrote).Append(number).Append(comment).ToString();
sb.Clear();
}
sw.Stop();
Console.WriteLine("StringBuilder: " + sw.ElapsedMilliseconds);

sw.Reset();
sw.Start();

for (var i = 0; i < n; i++)
{
var s = usr + name + wrote + number + comment;
}
sw.Stop();
Console.WriteLine("string concat: " + sw.ElapsedMilliseconds);

Console.ReadKey();

StringBuilder: 1296
string concat: 1734

По поводу изменения строк по указателю: я специально не приводил пример такой возможности, т.к. это не является хорошей практикой из-за интернирования.

const string CONST = "some string";

var a = "some string";
ReverseStringUnsafe(a);

switch (a)
{
case CONST: Debugger.Break(); break;
}

Тут дебаггер сработает, хотя этого программист может совсем не ожидать.

2

про дебагер по мне достаточно ожидаемо, ну да ладно.

>> Если каждый раз для сложения малого числа строк создавать новый экземпляр StringBuilder
поэтому более правильно задавать вопрос "в каких случаях, что лучше использовать для конкатенации строк", так как с одной стороны тем кто знает дается подсказка, что от него хотят услышать, с другой люди которые в лоб заучили "всегда использовать StringBuilder и без вариантов" тоже задумаются и возможно попытаются что-то обосновать.

А по поводу бенчмарков:
_sarcasm on_
смотрю на них и c радостью любуюсь простоте jit под c# =)
ни тебе прогрева, ни профайлинга, ни deadcodeelliminations, сказка, а не компилятор
_sarcasm off_

Алексей Данченко
Алексей Данченко Инженер-программист в ЛюксСофт
5

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

1

Ха. А я еще несколько раз переписывал коммент и остановился на достаточно приличном выражении "Пошли они лесом".

Конкурентов на девбай нет, ей богу.

0

О, хитрый план. Надо пойти "стукануть" на тутбай или онлайнер, что такое поле для деятельности пропадает.

0

Не думаю, что на девбае можно круто заработать. Хотя, я ж не девбай, не знаю.

drew
drew ведущий инженер-программист в SCAND
3

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

Андрей Митин
Андрей Митин System analyst в CTDEV
4

Оно понятно - удалить коммент проще, чем конвертить [code] в спан со стилем font-family: monospace; white-space: pre;

1

Это ж надо кому-то заплатить, хоть самую малость. А платить жааалко.

0

интересно, как долго вы искали фотку к посту.

0

JS. Ответ к 5 заданию: "В первом случае диалог покажется, т.к... ". наверное, опечатка.

Anonymous
Anonymous Старший разработчик в Adform BY
0

Где именно опечатка?

1

ну в первом случае alert() не сработает.. в условии стоит нестрогое сравнение же. может я ошибаюсь

Anonymous
Anonymous Старший разработчик в Adform BY
0

Верно, поправили. Спасибо!

Anonymous
Anonymous Frontend developer в Strevus
0

....

Спасибо! 

Получать рассылки dev.by про белорусское ИТ

Что-то пошло не так. Попробуйте позже