Русский
Русский
English
Статистика
Реклама

Career

А ты точно senior? или ожидания продуктовых компаний

07.01.2021 14:19:53 | Автор: admin

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

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

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

Для себя я выделил два основных направления - аутсорс и продуктовые компании.
Для аутсорс важнее широкий спектр технологий с которыми сталкивался кандидат.
В продуктовой будет важнее глубокое понимание технологий и принципы написания поддерживаемого кода.

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

Итак первое знакомство с кандидатом - резюме

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

На что обращаю внимание:
Как долго работает в одной компании, есть ли рост/смена позиций за время работы.

На чем акцент: технологии или подходы, задачи которые решал или технологии которыми пользовался.

Красным флагом могут быть:
частая смена проектов
большие количество проектов с CMS
пустое перечисление ключевых слов от CSS до IDE.

Если будет интересно к теме хорошего оформления резюме как-нибудь вернемся.

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

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

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

Под таблицей есть спойлер с картинкой если на вашем экране таблица поползла)

Junior

Middle

Senior

Архитектура приложений

Есть базовое понимание принципов ООП

Слышал про SOLID

Может придерживаться соглашений проекта и прослеживать аналогии

Знает пару паттернов

Хорошо понимает SOLID

Слышал про GRASP

Знает про модульную архитектуру

Знает какие есть паттерны, понимает когда нужно применять

Знает основные подходы к проектированию приложения(CQRS,ES,Modular,SOA)

Хорошо понимает как предупредить каскадные изменения

Может рассуждать про метрики качества кода

Знает паттерны вне GOF

Код

Знает базовые конструкции языка

С помощью гугла может решить основные задачи

Знает основные возможности языка, ряд популярных дополнений/библиотек

Может решить сложные задачи и направить Junior разработчика

Может грамотно построить структуру проекта

Код понятен легко читаем без лишнего усложнения

Структуры данных/алгоритмы

Знает какие есть структуры данных

Может подобрать подходящую для простых случаев

Может написать простой алгоритм, посчитать его сложность

Хорошо понимает структуры данных, в каком случае какую выбрать

Может выбирать, создавать сложные алгоритмы

При выборе алгоритма и структуры данных размышляет про эффективность выбора в разрезе RAM/CPU

Реляционные базы данных

Может строить простые запросы(выборки, простые джоины)

Понимает что такое индексы

Может построить отношения между таблицами

Может строить сложные запросы(сложные джоины, подзапросы, агрегации)

Понимает как построить оптимальные индексы

Может профилировать запросы, знает explain

Может спроектировать простую структуру базы данных

Понимает как работать с большими таблицами

Знает про репликацию

Может построить сложную структуру базы данных(шардинг, денормализация)

Знает ограничения и возможности популярных баз данных

Понимает ограничения CAP, PACELC

Безопасность

Слышал основные уязвимости

Знает основные OWASP уязвимости и как их предотвращать

Знает ряд техник для мониторинга, предотвращения уязвимостей.

Понимает как действовать при атаке

Тестирование

Есть базовое понимание для чего и как писать юнит тесты

Понимает различия между разными видами тестов

Может эффективно их писать

Понимает как избегать хрупких тестов

Знает разные подходы к написанию тестов(TLD, TDD)

Может рассуждать о пирамиде тестирования

Знает что дает и как создать нагрузочное тестирование

Как плюс знает AB тестирования

API

Знает базовые методы HTTP

Слышал про RPC,REST

Хорошо понимает принципы проектирования API

Знает какие есть варианты авторизаций

Знает основные подходы стандартизации/версионирования API

Может выбрать тип авторизации для проекта

Очереди/ Шина сообщений

Понимает зачем они и как работать на уровне интерфейса языка/библиотек

Понимает разницу между очередью и шинной данных

Знает основные проблемы воркеров и как из предотвращать (утечки памяти, перезапуск, мониторинг)

Знает основные решения по настройке, мониторингу очередей

Может выбрать подходящий брокер

Спроектировать подход к обработке данных (очередь, пайплайн, асинхронный ответ)

Многопоточность/ Асинхронность
Если поддерживает язык

Владеет на уровне интерфейса языка

Знает как работать с многопоточностью
(блокировки, синхронизация)

Знает как работать с асинхронностью

Понимает что такое итоговая согласованность

Когда и как лучше распараллелить процесс

Кеширование

Может работать на уровне интерфейса языка/библиотеки

Догадывается когда использовать

Знает как организовать кеш, какие бывают проблемы

Хорошо знаком с проблемами нагруженного кеша(прогрев, волна запросов, конкурентный доступ)

Инфраструктура/Сети

Знание базовых команд операционной системы

Знает какие этапы проходит запрос перед тем как попасть в приложение

Знаком с одним из средств виртуализации

Понимает какие вещи и как нужно настроить для продакшн среды

Понимает виртуализацию и контейнеризацию

Знает базовые сетевые протоколы TCP, UDP, HTTP, HTTPS

Понимает как устроена сеть DNS, NAT, OSPF, BGP, RIP

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

Хорошо понимает принципы работы CDN и как решать базовые проблемы

Знает ограничения текущей платформы, как их обойти

Метрики/логи

Знает зачем логи, как их писать

Знает варианты сбора логов

Понимает зачем проекту мониторинг, как им пользоваться

Может выбрать необходимые метрики

Знаком с рядом вариантов сбора метрик/логов

Способен настроить алертинг, сбор необходимых метрик

Желательно знакомство с TSDB

CVS/ Релиз процесс

Понимает зачем нужна CVS

Может выполнять базовые операции CVS

Может рассказать как сделать простой релиз через CVS и SSH руками

Хорошо знает команды CVS

Знает пару фреймворков построения процесса

Знает как работает CI

Может построить CI процесс, знает какие для этого есть инструменты

Хорошо знает подходы к ветвлению, может выбрать подходящий

PNG

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

Подробнее..

Перевод Вопросы, которые мне задавали на фронтенд-собеседованиях

02.09.2020 18:14:51 | Автор: admin

Всем привет. В сентябре OTUS вновь запускает целую линейку курсов по JavaScript. Прямо сейчас вы можете посмотреть запись открытого урока по курсу "JavaScript Developer. Professional", а также зарегистрироваться на дни открытых дверей по курсам "React.js Developer" и "JavaScript Developer. Basic". Ну а мы традиционно делимся с вами переводом полезного материала.


Фронтенд-собеседование (в 2 частях)

1. Вопросы, которые мне задавали на фронтенд-собеседованиях.

2. Ресурсы для подготовки к собеседованию (на должность фронтенд-разработчика).

Вопросы, которые задавали на фронтенд-собеседованиях


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


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

  • JS

  • Код

  • Задачи

  • Другие вопросы

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

Отредактировано 20.08.2020. Посмотреть изменения

JS

1. Есть многомерный массив глубиной N, который нужно сгладить. После сглаживания используйте его в качестве метода и привяжите к экземпляру объекта array.

Решение:

/** * [1,2,[3,4]] -> [1,2,3,4] */let arr = [1,2,[3,4, [5,6, [7, [8, 9, 10]]]]]function flatten(arr) {  return arr.reduce(function(acc, next){    let isArray =  Array.isArray(next)    return acc.concat(isArray ? flatten(next) : next)  }, [])}if (!Array.prototype.flatten) {  Array.prototype.flatten = function() {    return flatten(this)  }}console.log(arr.flatten());

2. Создайте промис с нуля

Решение:

class CustomPromise {  state = "PENDING"  value = undefined  thenCallbacks = []  errorCallbacks = []  constructor(action) {    action(this.resolver.bind(this), this.reject.bind(this))  }  resolver(value) {    this.state = "RESOLVED"    this.value = value    this.thenCallbacks.forEach((callback) => {      callback(this.value)    })  }  reject(value) {    this.state = "REJECTED"    this.value = value    this.errorCallbacks.forEach((callback) => {      callback(this.value)    })  }  then(callback) {    this.thenCallbacks.push(callback)    return this   }  catch (callback) {    this.errorCallbacks.push(callback)    return this   }}let promise = new CustomPromise((resolver, reject) => {  setTimeout(() => {    const rand = Math.ceil(Math.random(1 * 1 + 6) * 6)    if (rand > 2) {      resolver("Success")    } else {      reject("Error")    }  }, 1000)})promise  .then(function(response){    console.log(response)  })  .catch(function(error){    console.log(error)  })

3. Отфильтруйте список фильмов по среднему рейтингу, названию. Отсортируйте отфильтрованный список по любому полю.

Решение:

// O(M)function getMovies() {  return []; // [{id, name, year}]}// O(R)function getRatings() {  return []; // [{id, movie_id, rating}]   0 <= rating <= 10   // e.g 9.3}/** * minAvgRating -> *    avgRating >= minAvgRating * * sort -> *    name -> ascending order movies by name *   -name -> descending * *    avgRating *  * * search -> *   'ave' -> 'Avengers' *   'avengers' -> 'Avengers' *   'AvengersInfinitywar' -> 'Avengers' */const toLower = str => str.toLocaleLowerCase()const getAvrgRating = (movie, movingWithRatings) => {  let count = 0;  return movingWithRatings.reduce((acc, value, index) => {    const movieMatch = movie.id === value.movie_id    if (movieMatch) {      acc+=value.rating      count++    }    if (index === movingWithRatings.length - 1) {      acc = acc/count    }    return acc  }, 0)}const isSubString = (str1, str2) => {  str1 = toLower(str1.split(" ").join(""))  str2 = toLower(str2.split(" ").join(""))  if (str1.length > str2.length) {    return str1.startWith(str2)  } else {    return str2.startWith(str1)  }}const moviesList = getMovies()const movingWithRatings = getRatings();function queryMovies({ search, sort, minAvgRating }) {  let filteredMovies = movingWithRatings.filter(movie => getAvrgRating(movie, movingWithRatings) >= minAvgRating);  filteredMovies = filteredMovies.map(movie => moviesList.filter(listItem => listItem.id === movie.movie_id).pop())  filteredMovies = filteredMovies.filter(movie => isSubString(toLower(movie.name), toLower(search)))  filteredMovies = filteredMovies.sort((a, b) => {    const isDescending = sort[0] === '-' ? true : false    let sortCopy = isDescending ? sort.slice(1) : sort    const value1 = a[sortCopy]    const value2 = b[sortCopy]    if (isDescending) {      return value1 > value2 ? -1 : 1    }else {      return value1 < value2 ? -1 : 1    }  })  filteredMovies = filteredMovies.map(movie => ({    ...movie,    avgRating: movingWithRatings.filter(ratedMovie => ratedMovie.movie_id === movie.id)[0].rating  }))  return filteredMovies}

4. Загрузите все публикации и комментарии по URL-адресу конечной точки. Выполните следующее.

  • Соотнесите все комментарии с публикациями, к которым они относятся. В результате данные должны иметь следующую структуру.

Решение:

//service.jsconst POSTS_URL = `https://jsonplaceholder.typicode.com/posts`;const COMMENTS_URL = `https://jsonplaceholder.typicode.com/comments`;export const fetchAllPosts = () => {  return fetch(POSTS_URL).then(res => res.json());};export const fetchAllComments = () => {  return fetch(COMMENTS_URL).then(res => res.json());};import { fetchAllPosts, fetchAllComments } from "./service";const fetchData = async () => {  const [posts, comments] = await Promise.all([    fetchAllPosts(),    fetchAllComments()  ]);  const grabAllCommentsForPost = postId =>    comments.filter(comment => comment.postId === postId);  const mappedPostWithComment = posts.reduce((acc, post) => {    const allComments = grabAllCommentsForPost(post.id);    acc[post.id] = allComments;    return acc;  }, {});  console.log("mappedPostWithComment ", mappedPostWithComment);};fetchData();

5. Реализуйте метод getHashCode в экземпляре объекта string. Метод должен быть доступен для всех строк.

Решение:

let s1 = "sample"if (!String.prototype.getHashCode) {  String.prototype.getHashCode = function(){    console.log('String instance ', this)    return this  }}

6. Какой результат будет у приведенных ниже выражений?

    1+true    true+true    1+true    2 > 3    two>three

Решение:

221truefalsetrue

7. Реализуйте методы bind и reduce.

Решение:

//bindif (!Function.prototype.bind) {  Function.prototype.bind = function(...arg){    const func = this    const context = arg[0]    const params = arg.slice(1)    return function(...innerParam) {      func.apply(context, [...params, ...innerParam])    }  }}//reduceArray.prototype.reduce = function(func, initState) {  const arr = this  const callback = func  let init = initState  arr.forEach(function(value, index){      init=callback(init, value)  })  return init}

8. Реализуйте функцию debounce

Решение:

const debounce = function(func, interval) {  let timerId;  return function(e){    clearTimeout(timerId)    timerId = setTimeout(function(){      func.apply()    }, interval)  }}debounce(apiCall, 3000)

9. Реализуйте функцию throttle

Решение:

const throttle = (callback, interval) => {  let timerId;  let allowEvents = true;  return function() {    let context = this;    let args = arguments;    if (allowEvents) {      callback.apply(context, args)      allowEvents = false;      timerId = setTimeOut(function(){        allowEvents = true      }, interval)    }  }}

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

Нужно описать свой подход к решению, код писать не нужно. Возможны разные варианты решения.

Решение:

//С использованием метода setInterval, декоратора throttle и флаговsetInterval=>Endpoint=>Render//с инверсией управления//Endpoint=>Render=>setTimeout=>Endpoint=>Render=>SetTimeout...

11. Конвертируйте этот код, основанный на наследовании классов, в ES5.

class Parent(name){  constructor(name) {    this.name=name  }  getName(){return this.name}}class Children extends Parent {  constructor(props){    super(props)  }}

Решение:

function Parent(name) {  this.name = name}Parent.prototype.getName = function() {  return this.name}function Children(name){  Parent.call(this, name)}Children.prototype = new Parent()

12. Что выведет следующий код?

//Q.1var x = 1;var y = x;x = 0;console.log(x, y);//Q.2var x = [1];var y = x;x = [];console.log(x,y);//Q.3function Abc() { console.log(this); };Abc()new Abc();//Q.4var x = 1;var obj = {  x: 2,  getX: function () {    return console.log(this.x);  }};obj.getX()let a = obj.getXconsole.log(a)//Q.5//Как вывести 2 с использованием переменной a в коде из предыдущего вопроса?//Q.6console.log("A");setTimeout(() => console.log("B"), 0);setTimeout(() => console.log("C"), 0);console.log("D");//Q.7setTimeout(function() {  console.log("A");}, 0);Promise.resolve().then(function() {  console.log("B");}).then(function() {  console.log("C");});console.log("D");//Q.8let obj1 = {  a:1,  b:2}function mutate(obj) {  obj = {a:4, c:6}}console.log(obj1)mutate(obj1)console.log(obj1)

Решение:

//A.10 1//A.2[] [1]//A.3Будет выведен объект window//A.4Будут выведены значения 2 и 1//A.5a.call(obj);//A.6A, D, B , C//A.7D, B, C, A//A.8{ a: 1, b: 2 }{ a: 1, b: 2 }

13. Есть массив чисел. Выведите следующие элементы.

const list = [1,2,3,4,5,6,7,8]const filteredArray = list.filter(between(3, 6)) // [4,5]

Решение:

function between(start, end) {  return function (value,index) {    return value>start && value<end  }}

Алгоритмы

1. Рассмотрите последовательность.

A := 1B := A*2 + 2C := B*2 + 3 и так далее...

Напишите программу, которая :

  • выводит число, соответствующее определенной букве;

  • для строки, например 'GREP', вычисляет сумму чисел, соответствующих буквам строки (т.е. G + R + E + P) из этой последовательности;

  • и находит самую короткую строку, соответствующую большому числу (не больше максимального 32-разрядного целого числа).

Для решения последней задачи можно использовать жадный алгоритм. Числовые значения, соответствующие буквам, должны рассчитываться по мере необходимости. НЕ НУЖНО вычислять их заранее и сохранять в структуре данных.

Решение:

//A = 1//B = A*2 +2 //C = B*2+ 3//D = C*2+ 3var genCharArray = function(charA, charZ) {    var a = [], i = charA.charCodeAt(0), j = charZ.charCodeAt(0);    for (; i <= j; ++i) {        a.push(String.fromCharCode(i));    }    return a;}var charMap = {};var charArray = genCharArray('a', 'z');charArray.forEach(function(char, index){    charMap[char] = Number(index + 1);});var charSequence = function(char){    if(typeof char==="string"){        char = charMap[char];    }    if(char==1){        return 1;    }else{        return char + 2 * charSequence(char-1);    }}var input = process.argv[2];if(input.length===1){    console.log(charSequence(charMap[input]));}else if(input.length>1){    var charTotalSequence = input.split("").reduce(function(acc, curr){         return acc + charSequence(charMap[curr]);    },0);    console.log(charTotalSequence);}

2. Найдите в массиве пару чисел, сумма которых равна заданному числу.

Решение:

let nums = [2, 7, 10, 1, 11, 15, 9]let target = 11let numsMap = new Map()let pairs = nums.reduce((acc, num) => {  let numToFind = target - num  if (numsMap.get(numToFind)) {    return [...acc, [num, numToFind]]  } else {    numsMap.set(num, true)    return [...acc]  }}, [])console.log("Pairs ", pairs)

3. Найдите локальный максимум в заданном массиве. Локальный максимум это элемент, значение которого превышает значения элементов, расположенных справа и слева от него. Я использовал нотацию O(n). Это очевидное решение, которое можно оптимизировать.

Решение:

let x = [1, 2, 3, 5, 4] //Результаты: 5if x.length == 1 return x[0]else  let i = 1 for(;i<x.length-1;i++){  if x[i-1]<x[i] and x[i] > x[i+1] return x[i] } if x.length - 1 == i return x[i]

4. Поверните матрицу на 90 градусов по часовой стрелке. Решение должно выполняться в памяти, содержащей входные данные (алгоритм in-place, на месте).

leetcode

Решение:

[ [1, 2, 3], [4, 5, 6], [7, 8, 9]]//Сначала транспонируем матрицу.//После транспонирования матрица будет выглядеть так.[ [1, 4, 7], [2, 5, 8], [3, 6, 9]]//Теперь остается всего лишь изменить порядок элементов массива на обратный.//В результате матрица будет выглядеть так.[ [7, 4, 1], [8, 5, 2], [9, 6, 3]]//Первоначальная матрица развернута на 90 градусов.

5. Максимальная сумма подмассивов по модулю M.

Решение

6. Найдите в массиве три элемента, сумма которых равна заданному числу.

Решение:

let x = [1, 2, 3, 4, 5]let target = 7let found = []const twoPointer = (l ,r, current) => {  while(l<r){    const totalSum = current + x[l] + x[r]    if (totalSum === target) {      found.push([current, x[l], x[r]])      return    } else if (totalSum > target) {      r--    } else {      l++    }  }}const threeSum = (x, target) => {    for (let i=0;i<x.length;i++) {      const current = x[i];      let leftPointer = i+1      let rightPointer = x.length - 1      if (current+x[leftPointer]+x[rightPointer] === target) {        found.push([current, x[leftPointer], x[rightPointer]])      } else {        twoPointer(leftPointer, rightPointer, current)      }  }  return found}

7. Есть строка и целое число k. Вычислите количество подстрок, в которых каждый уникальный символ встречается ровно k раз.

ссылка

Решение:

const subStrHasSameCharCount = (str, startIndex, endIndex, totalHop) => {  let charMap = {}  for (let k=startIndex;k<endIndex;k++) {    let currentChar = str[k]    if (charMap[currentChar]) {      charMap[currentChar]++    } else {      charMap[currentChar] = 1    }  }  let totalCount = Object.values(charMap).length > 0  return totalCount ? Object.values(charMap).every(item => item == totalHop) : false}const characterWithCountK = (str, k) => {  if (k == 0) return ''  let count = 0  let initialHop = k  while (initialHop < str.length) {    for (let j=0;j<str.length;j++) {      let startIndex = j      let endIndex = j + initialHop      if(endIndex > str.length) continue      count = subStrHasSameCharCount(str, startIndex, endIndex, k)        ? count + 1: count    }    initialHop+=k  }  count = subStrHasSameCharCount(str, 0, initialHop, k)        ? count + 1: count  return count}let str = 'aabbcc'let k = 2console.log(characterWithCountK(str, k))

8. Есть две строки s1 и s2, каждая из которых содержит символы от a до z в разном порядке. Проверьте, можно ли переставить символы в строке s1 таким образом, чтобы строки стали равными.

Решение:

let s1 = 'dadbcbc'let s2 = 'ccbbdad'let charMap = {}const canBeRearranged = (s1, s2) => {  if(s1.length!==s2.length){    return false  }  for(let i=0;i<s1.length;i++){    const charFromString1 = s1[i]    const charFromString2 = s2[i]    if(charFromString1 in charMap){      charMap[charFromString1]++    } else {      charMap[charFromString1] = 1    }    if(charFromString2 in charMap){      charMap[charFromString2]--    } else {      charMap[charFromString2] = -1    }  }  for(let x in charMap){    if (charMap[x]!==0){      return false    }  }  return true}canBeRearranged(s1, s2)

9. Есть массив с переменной начальной длиной. Расположите элементы массива в случайном порядке.

Решение:

const swap = (index1, index2, arr) => {  let temp = arr[index1]  arr[index1] = arr[index2]  arr[index2] = temp}const shuffle = (arr) => {  let totalLength = arr.length  while(totalLength > 0) {    let random = Math.floor(Math.random() * totalLength)    totalLength--    swap(totalLength, random, arr)  }  return arr}let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]arr = shuffle(arr)

10. Вычислите сумму всех элементов многомерного массива с бесконечной глубиной.

Решение:

let arr = [4, 5, 7, 8, [5, 7, 9, [3, 5, 7]]]let sum = 0const calculateSum = (arr) => {  arr.reduce(function(acc, currentVal) {    const isEntryArray = Array.isArray(currentVal)    if (isEntryArray) {      return acc.concat(calculateSum(currentVal))    } else {      sum+=currentVal      return acc.concat(currentVal)    }  }, [])}calculateSum(arr)console.log(sum)

11. Сгладьте многоуровневый вложенный объект.

Решение:

const obj = {  level1: {    level2: {      level3: {        more: 'stuff',         other: 'otherz',        level4: {          the: 'end',        },      },    },    level2still: {      last: 'one',    },    am: 'bored',  },  more: 'what',  ipsum: {    lorem: 'latin',  },};var removeNesting = function(obj, parent){  for (let key in obj){    if (typeof obj[key] === "object") {      removeNesting(obj[key], parent+"."+key)    } else {      flattenedObj[parent+'.'+key] = obj[key]    }  }}let flattenedObj = {}const sample = removeNesting(obj, "");console.log(flattenedObj);

12. Есть данные в формате json, где каждый объект обозначает каталог и может, в свою очередь, содержать другой вложенный объект. Выведите на экран структуру каталога.

Решение

13. Есть массив объектов, содержащих информацию о сотрудниках (у каждого сотрудника есть несколько подчиненных). На основании этих данных постройте иерархию сотрудников.

Решение:

const employeesData = [{  id: 2,  name: 'Андрей (главный технический директор)',  reportees: [6] }, {  id: 3,  name: 'Алексей (главный операционный директор)',  reportees: []}, {  id: 6,  name: 'Александр (руководитель инженерной группы)',  reportees: [9] }, {  id: 9,  name: 'Анатолий (старший инженер)',  reportees: []}, {  id: 10,  name: 'Антон (генеральный директор)',  reportees: [2, 3],}];/*A (генеральный директор)----B (главный технический директор)--------D (руководитель инженерной группы)------------E (старший инженер-разработчик)----C (главный операционный директор)*/const findCeo = (currentEmp) => {  let parentEmployee = employeesData.filter(emp => emp.reportees.indexOf(currentEmp.id) > -1)  if (parentEmployee && parentEmployee.length > 0) {    return findCeo(parentEmployee[0])  } else {    return currentEmp  }}const logHierarchy = (currentEmp, indent) => {  console.log("-".repeat(indent) + currentEmp.name)  indent+=4;  for(let i=0;i <currentEmp.reportees.length;i++) {    let employee = employeesData.filter(emp => emp.id === currentEmp.reportees[i])    logHierarchy(employee[0], indent)  }}const traverse = (employee) => {  let ceo = findCeo(employee)  logHierarchy(ceo, 0)}traverse(employeesData[0])

14. Преобразуйте заданную матрицу в спиральную и выведите на экран

const inputMatrix = [  [1, 2, 3, 4,  5],  [6, 7, 8, 9, 10],  [11,12,13,14,15],  [16,17,18,19,20],]const exprectOutput = [1,2,3,4,5,10,15,20,19,18,17,16,11,6,7,8,9,14,13,12]

Решение:

function spiralParser(inputMatrix){  const output = [];  let rows = inputMatrix.length;  let cols = rows > 0 ? inputMatrix[0].length : 0;  //singleEmptyRow => Edge case 1 //[]  if (rows === 0) {    return []  }  if (rows === 1) {    //singleElementRowNoCol => Edge case 2 //[[]]    if (cols === 0) {      return []    } else if (cols === 1){      //singleElementRow => Edge case 3 //[[1]]      output.push(inputMatrix[0][0])      return output     }  }  let top = 0;  let bottom = rows - 1;  let left = 0;  let right = cols - 1;  let direction = 0;  //0 => left->right  //1 => top->bottom  //2 => right->left  //3 => bottom->top  while(left <= right && top <= bottom) {    if(direction === 0) {      //left->right      for (let i=left; i<=right;i++) {        output.push(inputMatrix[top][i])      }      top++;    } else if (direction === 1) {      //top->bottom      for (let i=top; i<=bottom;i++) {        output.push(inputMatrix[i][right])      }      right--    } else if (direction === 2) {      //right->left      for (let i=right; i>=left;i--) {        output.push(inputMatrix[bottom][i])      }      bottom--    } else if (direction === 3) {      //bottom->top      for (let i=bottom; i>=top;i--) {        output.push(inputMatrix[i][left])      }      left++    }    direction = (direction + 1) % 4  }  return output;}console.log(spiralParser(inputMatrix2))

15. Найдите символ с максимальным количеством последовательных вхождений в заданной строке.

let str = 'bbbaaaaccadd'; //Больше последовательных вхождений (4) у символа a

Решение:

//псевдокодmaxNow = если длина входной строки равна1 или больше 1 ? 1 : 0maxOverall = если длина входной строки равна1 или больше 1 ? 1 : 0для символов входной строки с индексом 1 и больше  если символ равен предыдущему символу    maxNow++ //увеличить на 1    maxOverall = max(maxOverall, maxNow)  иначе если символ не равен предыдущему символу        maxNow = 1

16. Есть массив переменной длины. Переместите все двойки (2) в конец массива.

let inputArr = [2,9,1,5,2,3,1,2,7,4,3,8,29,2,4,6,54,32,2,100]//ouput => [9,1,5,3,1,7,4,3,8,29,4,6,54,32,100,2,2,2,2,2]

Решение:

let slowRunner = 0for (let fastRunner=0;fastRunner<arr.length;fastRunner++) {  if (arr[fastRunner]!==2 && arr[slow] == 2) {    [arr[fastRunner], arr[slow]] = [arr[slow], arr[fastRunner]]    slowRunner++  }}

17. Выведите список в обратном порядке

//На входе = 1 -> 2 -> 3 -> 4 -> 5 -> 6//В результате = 1 <- 2 <- 3 <- 4 <- 5 <- 6

Решение:

//псевдокодlet current = headlet prev = nulllet next = nullwhile(current) {  next = current.next  current.next = prev  prev = current  current = next}

18. Реализуйте прямой обход дерева с помощью итераций (без рекурсии)

Решение:

//псевдокодconst preorder = (root) => {  let stack = []  stack.push(root)  пока(переменная stack содержит данные) {    let current = stack.pop()    console.log(current.value)    if (current.right) {      stack.push(current.right)    }    if (current.left) {      stack.push(current.left)    }  }}

Задачи

1. Разработайте систему для автоматизации парковки, отвечающую следующим требованиям.

  • Она хранит данные об N автомобилях. Она обрабатывает данные о наличии парковочных мест.

  • Она регистрирует въезжающие и выезжающие автомобили.

  • Автоматизированная система учета автомобилей регистрирует все въезжающие и выезжающие автомобили по следующим данным: регистрационный номер, цвет, парковочное место.

Система должна предоставлять следующую информацию:

  • регистрационные номера всех автомобилей определенного цвета;

  • номер парковочного места автомобиля по регистрационному номеру;

  • парковочные места автомобилей определенного цвета.

  • список свободных парковочных мест.

Требования:

  • для структурирования кода можно пользоваться классами/структурами;

  • решение должно быть расширяемым для последующего применения.

Некоторые принципы разработки кода:

  • модульность кода;

  • соглашения об именовании;

  • принципы SOLID.

Решение

2. Создайте React-компонент Ping, при использовании которого API будет отправлять запрос по заданному URL. Если возвращается код состояния 200, это означает, что пользователь в Сети. Если возвращается любой другой код состояния, это означает, что пользователь не в Сети.

Попробуйте изменить статус из сетевой панели dev tools.

Решение

3. Создайте конструктор динамических форм на базе json. Формы должны группироваться по id. В каждой группе может быть другая вложенная группа.

Решение

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

Решение

5. Создайте строку поиска по списку пользователей.

Объект user (пользователь) включает следующие поля.

id: уникальный идентификаторимя: имя пользователятовары: список товаров, заказанных пользователемадрес: адрес пользоиндекс: почтовый индекс пользователя

Поиск должен осуществляться по всем полям.

Результаты поиска должны выводиться в виде карточки пользователя.

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

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

(Навигация будет осуществляться с помощью клавиатуры, если мышь наведена на элемент списка. Если клавиатура не используется, навигация будет осуществляться с помощью мыши.)

Это похоже на принцип поиска в YouTube

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

Подсвеченная карточка (с помощью клавиатуры или мыши) появляется в области просмотра полностью.

Решение

Другие вопросы

1. Как бы вы структурировали интерфейсное приложение? (посмотреть)
2. Реализуйте стратегию ленивой загрузки (посмотреть)
3. Что такое серверный рендеринг?
4. Как развернуть React-приложение в промышленной среде?
5. Что такое сервис-воркер (веб-воркер)?
6. Как оптимизировать веб-приложение и повысить его производительность?
7. Расскажите о стратегиях кэширования на стороне клиента.
8. Что такое CORS?
9. Назовите компоненты высшего порядка в React.
10. Как работает функция connect в Redux?
11. Что такое PureComponent в React?

Ресурсы

ссылка


Узнать подробно о курсе:

Подробнее..

Онлайн-лекция Какие навыки нужны разработчику для карьерного роста

27.09.2020 14:13:04 | Автор: admin


28 сентября приглашаем на онлайн-лекцию о развитии карьеры в IT.

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

Директор центра подбора IT-специалистов SymbioWay Даниил Пилипенко прочертит карьерный путь разработчика. Расскажет, что такое soft skills и почему их важно развивать. Поможет выяснить, что важнее для карьерного роста: трудоголизм или трудолюбие.

Регистрация


Об эксперте


Даниил Пилипенко директор центра подбора IT-специалистов SymbioWay.
Старший преподаватель Skillbox по Java и веб-верстке.

По теме:

Подробнее..

Мы не рабы, рабы не мы

15.06.2021 20:16:32 | Автор: admin


Мы не рабы, рабы не мы это фраза из первой советской азбуки Долой неграмотность: Букварь для взрослых от 1919 года. Данная книга стимулировала миллионы людей в нашей стране менять свой быт, сознание и даже политический строй. Прошло сто лет. И кажется на какой-то развилке общество повернуло налево.

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

От плантации до...


В начале байка из жизни американских рабов на плантациях сахарного тростника. Как вы знаете, на заре становления США в этой стране использовали рабский труд. Невольников привозили на плантации и безбожно угнетали. Но и там не обходилось без своих ноу-хау.

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

Все на продажу


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

Работать в таких больших и успешных корпорациях хочется многим. Но дьявол, как всегда, в деталях. Чем крупнее и географически шире ритейлер, тем противоречивее впечатления от работы в нем у сотрудников конкретных магазинов и складов у тех, кто в буквальном смысле своими руками делает этих супергероев FT-500, Forbes и прочих знаковых рейтингов.

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

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

Болеть нельзя уволить


Три года назад наделал шума отчет бюро по рабочим конфликтам A Better Balance, рассказывающий о ситуации в Walmart. Опрошенные сотрудники крупнейшего мирового ритейлера рассказывали, что панически боятся болеть, брать больничные, сидеть с детьми.

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

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

Наиболее яркие цитата сотрудников Walmart из отчета A Better Balance:
У моей дочери был эпилептический припадок. Я отпросился с работы. Всю ночь не спал, просидев рядом с дочерью. А утром просто уснул на работе. Менеджер послала меня в больницу. На следующий день меня уволили за прогул (штат Огайо, магазин)

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

В комментарии Business Insider по поводу изложенного в отчете представитель Walmart тогда заявил: В нашей компании работают люди, получающие оплату пропорционально отработанным часам. Мы просто не можем себе позволить, чтобы эти сотрудники отсутствовали слишком долго на рабочем месте. Однако ни о каких нарушениях речи и быть не может. Мы понимаем, что случаются непредвиденные обстоятельства, когда сотруднику необходимо отлучиться, и мы всегда идем навстречу. Это касается и тех, кто работает не сдельно, а в штате. Любой сотрудник может всегда рассчитывать на отпуск или больничный. Мало того, политика нашей компании предполагает устройство на работу людей с ограниченными возможностями.

Была у сотрудников Walmart даже война с роботами, в которой они (сотрудники) победили. Об этом рассказывала The Washington Post. Ритейлер несколько лет пытался автоматизировать процессы инвентаризации. В результате у живых сотрудников уменьшался прописанный в должностных инструкциях объем функционала и им снижали зарплату.

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

На работу в Мордор


Осенью прошлого года гуманитарный скандал тряхнул крупнейшего онлайн-ритейлера Amazon. Open Markets Institute выпустила отчет о том, как работают на складах Amazon. Он был сделан по информации, полученной от сотрудников и из разных медиа. Отчет представил международного бизнес-гиганта чуть ли не как толкиеновский Мордор с его всевидящим оком.

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

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

Водители Amazon не могут отклоняться от заданных маршрутов (все перемещения отслеживаются) и обязаны доставить вовремя 999 заказов из 1000. Доставил меньше увольнение.

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

Больше контроля, больше зарплата


Было бы странно не вспомнить о продолжающейся пандемии коронавируса и массовом исходе персонала по всему миру на удаленку. Для миллионов владельцев бизнеса подобная миграция стала причиной перманентного стресса. Страх утратить контроль над рабочими процессами популярная фобия в современном капиталистическом мире. Какой выход? Правильно, внедрение ПО, повышающего контроль над сотрудниками.

Российская компания Stakhanovets, образованная в 2009 году, специализируется на разработке программных решений для мониторинга сотрудников. Продукт Стахановец позволяет руководителям компаний понимать, насколько эффективны, надежны и безопасны их сотрудники (описание с официального сайта).

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

Другая программа Yva разработка Давида Яна, основателя российской компании ABBYY. Программа мониторит поведение каждого сотрудника по содержимому электронной почты, CRM, системе документооборота. А еще в ней можно проводить опросы работников по самым разным темам от степени удовлетворенности работой до того, как специалист видит свое будущее в компании. Хотя, надо отметить, что при всем при этом софт относительно этичен личные мессенджеры не контролируются, публикации в соцсетях и обновления на LinkedIn также не отслеживаются.

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

Цвет настроения разный


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

Но доверие это всегда сложно и долго. А бизнес ждать не может. Поэтому если ты идешь работать в крупную компанию, значит принимаешь ее неизбежную небирюзовость. Или это заблуждение? Давайте обсудим в комментариях границы личного и корпоративного в рабочем пространстве? Где начинается и заканчивается ваше Privacy?
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru