Skip to content

Latest commit

 

History

History
356 lines (247 loc) · 40.8 KB

Interview questions - Programming.md

File metadata and controls

356 lines (247 loc) · 40.8 KB

Шпаргалка по общим вопросам программирования и frontend-разработки

Чистые функции


  • Чистая функция:

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

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

    Пример чистой функции - не меняет свои входные данные и предсказуемо возвращает один и тот же результат для одинаковых аргументов:

      function sum(a, b) {
        return a + b;
      }
    

    Пример нечистой функции — записывает данные в свои же аргументы:

    function withdraw(account, amount) {
        account.total -= amount;
      }
    
Инкапсуляция = сокрытие лишних деталей
Интерфейс - то как мы взаимодействуем с чем-то - интерфейс объекта - какие свойства и методы у него есть - интерфейс функции - её имя, какие параметры мы в неё передаём, какой ответ получаем...
Идемпотентность — свойство объекта или операции при повторном применении операции к объекту давать тот же результат, что и при первом.
Детерминированность - для одних и тех же исходных алгоритм выдаёт тот же результат. Результат однозначно определяется исходными данными.
Иммутабельность - неизменяемость. Функция не меняет входящие данные. Делает копию, и работает уже с ней.


Debounce

"Декоратор" который возвращает обертку. Она откладывает вызов исходной функции на определенное время.

Декораторы (микропаттерны оптимизации) функций позволяют добавить дополнительное поведение функции, не изменяя ее.

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

Возможны два варианта:

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

Зачем?
Обычно debounce используют, если исходная функция вызывается чаще, чем это требуется.
Например, DOM-события mousemove, resize, scroll генерируют очень частые вызовы обработчиков, поэтому в ряде случаев было бы полезно обернуть такие обработчики в debounce.
Другое применение – контроль пользовательского ввода текста: если при изменении поля INPUT требуется передавать на сервер текущее введенное значение, это может создать большое количество однотипных запросов, особенно если пользователь печатает очень быстро. В этом случае тоже весьма кстати будет ограничить число вызовов обработчика с помощью debounce.
Функция debounce крайне полезна, когда дело доходит до производительности обработчиков событий.

Ссылки:


Мемоизация

Разновидность кэширования.

Запоминаем предыдущие результаты вызова функции, и если вызывается снова - используем их из кэша

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

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

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

Если вы работаете с React/Redux, можете взглянуть на reselect. Тут используется селектор с мемоизацией. Это позволяет выполнять вычисления только в том случае, если в соответствующей части дерева состояний произошли изменения.

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

Ссылки


Советы по оптимизации рендеринга web-страниц

Оптимизация производительности рендеринга

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

  • JavaScript. В предыдущих материалах этой серии мы рассказывали о том, как писать оптимизированный JS-код, не блокирующий пользовательский интерфейс, эффективно использующий память и реализующий другие полезные техники. Когда речь идёт о рендеринге, нам нужно учитывать то, как JS-код будет взаимодействовать с элементами DOM на странице. JavaScript может вносить множество изменений в пользовательский интерфейс, особенно если речь идёт об одностраничных приложениях.
  • Вычисление стилей. Это — процесс определения того, какое CSS-правило применяется к конкретному элементу с учётом соответствующих этому элементу селекторов. После определения правил осуществляется их применение и вычисление итогового стиля для каждого элемента.
  • Формирование макета страницы. После того, как браузер узнает о том, какие стили применяются к элементу, он может приступить к вычислению того, как много места на экране займёт этот элемент, и к нахождению его позиции. Модель макета веб-страницы указывает на то, что одни элементы могут влиять на другие элементы. Например, ширина элемента может влиять на ширину дочерних элементов, и так далее. Всё это означает, что процесс формирования макета — это задача, требующая интенсивных вычислений. Кроме того, вывод элементов выполняется на множество слоёв.
  • Отрисовка. Именно здесь выполняется преобразование всего, что было вычислено ранее, в пиксели, выводимые на экран. Этот процесс включает в себя вывод текста, цветов, изображений, границ, теней, и так далее. Речь идёт о каждой видимой части каждого элемента.
  • Компоновка. Так как части страницы вполне могут быть выведены на различных слоях, их требуется совместить в едином окне в нужном порядке, что приведёт к правильному выводу страницы. Это очень важно, особенно — для перекрывающихся элементов.

Оптимизация JS-кода

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

  • Избегайте использования функций setTimeout() и setInterval() для обновления внешнего вида элементов страниц. Эти функции вызывают коллбэк в некоторый момент формирования кадра, возможно, в самом конце. Нам же нужно вызвать команду, приводящую к визуальным изменениям, в начале кадра, и не пропустить его.
  • Переносите длительные вычисления в веб-воркеры.
  • Используйте для выполнения изменений в DOM микро-задачи, разбитые на несколько кадров. Этим следует пользоваться тогда, когда задача нуждается в доступе к DOM, а доступ к DOM, из веб-воркера, например, получить нельзя. Это означает, что большую задачу нужно разбить на более мелкие и выполнять их внутри requestAnimationFrame, setTimeout, или setInterval, в зависимости от особенностей задачи.

Оптимизация CSS

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

  • Уменьшите сложность селекторов. Использование сложных селекторов может привести к тому, что работа с ними займёт более 50% времени, необходимого для вычисления стилей элемента, остальное время уйдёт на конструирование самого стиля.
  • Уменьшите число элементов, для которых нужно выполнять вычисление стилей. То есть, лучше, если изменение стиля будет направлено на несколько элементов, а не на всю страницу.

Оптимизация макета

Пересчёт макета страницы может требовать серьёзных системных ресурсов. Для оптимизации этого процесса примите во внимание следующее.

  • Уменьшите число ситуаций, приводящих к пересчёту макета. Когда вы меняете стили, браузер выясняет, требуется ли пересчёт макета для отражения этих изменений. Изменения свойств, таких, как ширина, высота, или позиция элемента (в целом, речь идёт о геометрических характеристиках элементов), требуют изменения макета. Поэтому, без крайней необходимости, не меняйте подобные свойства.
  • Всегда, когда это возможно, используйте модель flexbox вместо более старых моделей создания макетов. Эта модель работает быстрее, чем другие, что может дать значительный прирост производительности.
  • Избегайте модели работы с документом, предусматривающей периодическое изменение параметров элементов и их последующее считывание. В JavaScript доступны параметры элементов DOM (вроде offsetHeight или offsetWidth) из предыдущего кадра. Считывание этих параметров проблем не вызывает. Однако, если вы, до чтения подобных параметров, меняете стиль элемента (например, динамически добавляя к нему какой-то CSS-класс), браузеру потребуется потратить немало ресурсов для того, чтобы применить изменения стиля, создать макет и возвратить в программу нужные данные. Это может замедлить программу, подобного стоит избегать всегда, когда это возможно.

Оптимизация отрисовки

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

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

Оптимизация производительности анимаций

Как и за всё остальное в этом мире, за анимацию надо платить. При этом анимирование некоторых свойств обходится «дешевле», чем анимирование других. Например, анимирование свойств width и height элемента приводит к изменению его геометрии и может привести к тому, что другие элементы на странице переместятся или изменят размер. Этот процесс называется формированием макета страницы. Об этом мы говорили в одном из предыдущих материалов.

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

Ссылки


ООП - некоторые понятия


Объе́ктно-ориенти́рованное программи́рование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования.

Базовые понятия

  • Класс - абстрактное описание автомобиля. Чертёж
  • Объект - конкретная реализация автомобиля, данная машина
  • Свойства - характеристики харакерные для всех машин. Количество колес, цвет, количество бензина...
  • Методы - команды, на которые может реагировать машина. По сути функции, которые может вызывать каждый объект.
  • Геттеры и сеттеры - спец. методы, для добавления/получения свойств объекта (чтоб не использовать приватные свойста)

Базовые принципы ООП

  • Наследование — механизм, который позволяет описать новый класс на основе существующего (родительского). При этом свойства и функциональность родительского класса заимствуются новым классом. Нужно, прежде всего, для повторного использование кода. Cвойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс — потомком, наследником, дочерним или производным классом.
  • Абстракция - выделение главных, наиболее значимых характеристик предмета и отбрасывание второстепенных.
  • Инкапсуляция - ограничение доступа к данным и возможностям их изменения. Свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе.
  • Полиморфизм — возможность работать с несколькими типами так, будто это один и тот же тип. При этом поведение объектов будет разным в зависимости от типа, к которому они принадлежат. Cвойство системы, позволяющее использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.

Разные модели (подходы) ООП

  • Компонентно-ориентированное программирование
  • Прототипно-ориентированное программирование
  • Агентно-ориентированное программирование

Шаблоны проектирования "банды четрыёх" GoF

Принципы SOLID

S: Single Responsibility Principle (Принцип единственной ответственности) Каждый класс должен решать лишь одну задачу.
O: Open-Closed Principle (Принцип открытости-закрытости). Программные сущности (классы, модули, функции) должны быть открыты для расширения, но не для модификации.
L: Liskov Substitution Principle (Принцип подстановки Барбары Лисков). Необходимо, чтобы подклассы могли бы служить заменой для своих суперклассов. Классы-наследники могли бы использоваться вместо родительских классов, от которых они образованы, не нарушая работу программы. Если оказывается, что в коде проверяется тип класса, значит принцип подстановки нарушается.
I: Interface Segregation Principle (Принцип разделения интерфейса). Создавайте узкоспециализированные интерфейсы, предназначенные для конкретного клиента. Клиенты не должны зависеть от интерфейсов, которые они не используют.
D: Dependency Inversion Principle (Принцип инверсии зависимостей). Объектом зависимости должна быть абстракция, а не что-то конкретное. Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Ссылки


Другие методологии программирования

  • императивное - вычисления описываются в виде инструкций, шаг за шагом изменяющих состояние программы.
  • декларативное - описываем не поведение, а состояния компонентов (в зависимости от разных данных) + переключаемся между этими состояниями.
  • структурное - декомпозиция. По-прежнему оперируем состоянием и инструкциями, однако вводится понятие составной инструкции (блока), инструкций ветвления и цикла.
  • процедурное - исходная задача разбивается на меньшие (с помощью процедур) и это происходит до тех пор, пока решение всех конкретных процедур не окажется тривиальным.
  • модульное - разделение функциональности на законченные блоки. Программа описанная в стиле модульного программирования — это набор модулей. Что внутри, классы, императивный код или чистые функции — не важно. Благодаря модулям впервые в программировании появилась серьезная инкапсуляция — возможно использовать какие-либо сущности внутри модуля, но не показывать их внешнему миру.
  • функциональное - всё есть чистая функция, даже числа. Важно "отсутсвие состояния"
  • обобщённое - разделение на шаблоны
  • реактивное - ориентированное на потоки данных и распространение изменений. Должна существовать возможность легко выражать статические и динамические потоки данных, а также нижележащая модель исполнения должна автоматически распространять изменения благодаря потоку данных.
  • всякие экзотические - автоматное, аппликативное, аспект/агент/компонент-ориентированное...
    Немного подробнее: «Забытые» парадигмы программирования ...

Ссылки


MVC для web

Model-View-Controller (модель-вид-контроллер)
Конструкционный шаблон (архитектурный паттерн), описывает способ построения структуры приложения, сферы ответственности и взаимодействие каждой из частей в этой структуре.

Основаня идея: нужно чётко разделять ответственность за различное функционирование в наших приложениях. Делим приложение на три основных компонента, каждый из которых отвечает за различные задачи.

  • Model - обработка данных и логика приложения
  • View - представление данных пользователю (в любом формате)
  • Controller - обработка действий пользователя, вызов соответствующих рессурсов

Концепция описана в 1979 году. Стала популярна благодаря включению в две среды разработки: Struts и Ruby on Rails.

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

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

Только данные, которые должны быть обработаны в соответствии с правилами (дата не может указывать в будущее, e-mail должен быть в определённом формате, имя не может быть длиннее Х символов, и так далее).

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

View Представление (Вид) отвечает за видимое пользователю отображение этих данных (то есть, в применении к вебу, формирует отдаваемый сервером браузеру пользователя HTML/CSS).

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

Controller Контроллер управляет всем этим оркестром. Содержит организационную логику.

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

Стандартная схема работы:

  • Контроллер получает запрос
  • Посылает команду Модели на работу с данными
  • В заивисмости от ответа Модели Контроллер решает -какое из Представлений вызвать для формирования итогового ответа на изначальный Запрос
  • Представление по комнаде Контроллера менет отображение информации на экране.
  • Пользователь взаимодействует с Представлением (кликает по кнопке, например), и тем самым формирует новый запрос к Контроллеру

Веб приложение обычно состоит из набора контроллеров, моделей и видов. 0 Модификации
Есть много модификаций швблона MVC -HMVC (Hierarchical MVC) и другие

//ToDo - дополнить

Ссылки


Некоторые принципы программирования

Некоторые принципы Объектно Ориентированнаого Дизайна

  • Закон Деметры (англ. Law of Demeter, LoD) - каждый программный модуль:
    • должен обладать ограниченным знанием о других модулях: знать о модулях, которые имеют «непосредственное» отношение к этому модулю.
    • должен взаимодействовать только с известными ему модулями «друзьями», не взаимодействовать с незнакомцами.
    • обращаться только к непосредственным «друзьям». Ссылки
    • habr
    • wikipedia
  • GRASP (general responsibility assignment software patterns) — общие шаблоны распределения ответственностей
    • Ответственность должна быть назначена тому, кто владеет максимумом необходимой информации для исполнения. Постоянно используешь в объекте какой-то внешний метод? Скорее всего, этот метод должен быть в этом объекте
    • высокое сцепление - код выполняющий одну задачу, должне быть в одном месте
    • низкая связность - модули не должны зависеть друг от друга (если они ссылаются друг на друга - это то же самое что у вас один большой модуль)
    • ... (всего 9 принципов)
    • Wikipedia
  • CQS (Command Query Separation)
    • метод должен быть либо командой, выполняющей какое-то действие, либо запросом, возвращающим данные, но не одновременно.
    • Другими словами, задавание вопроса не должно менять ответ.
    • Более формально, возвращать значение можно только чистым, не имеющим побочных эффектов методам. Следует отметить, что строгое соблюдение этого принципа делает невозможным отслеживание количества вызовов запросов.
    • Другими словами: если я спрашиваю у объекта "Ты админ?", он должен вернуть только tru или false. И не должен внутри заниматься изменением состояния
    • Wikipediz
  • Single level of Abstraction (один уровень абстракции)

См видео "Ментальное программирование"




Legmo, 2019