Телеграм и демоны
Привет, кто решил остаться. Вы клёвые!
Щас расскажу важный момент о ботах Телеги.
В любом гайде есть код бота и так далее, но как держать его запущенным круглосуточно с закрытой консолью - умалчивается.
Я нашел два пути это сделать:
1. Создать демона через systemctl. Наиболее правильный и надежный способ. Пишем конфиг, запускаем.
2. Повесить терминал на screen. Не так быстро, зато доки читать не надо:
Кстати, консольный Vim - это просто! Жмякай i для редактирования, потом ESC + :wq для сохранения и выхода.
#бот #nodejs
Привет, кто решил остаться. Вы клёвые!
Щас расскажу важный момент о ботах Телеги.
В любом гайде есть код бота и так далее, но как держать его запущенным круглосуточно с закрытой консолью - умалчивается.
Я нашел два пути это сделать:
1. Создать демона через systemctl. Наиболее правильный и надежный способ. Пишем конфиг, запускаем.
2. Повесить терминал на screen. Не так быстро, зато доки читать не надо:
sudo apt install screen
screen -S botfolder
node bot.js
И второй момент - где хостить. Я просто купил VPS на отечественном хостинге. Облака, heroku и так далее - экономия на спичках. На VPS накатил Убунту, туда - ноду, а дальше дело техники.Кстати, консольный Vim - это просто! Жмякай i для редактирования, потом ESC + :wq для сохранения и выхода.
#бот #nodejs
Пара тонкостей работы с сетью
- Как определить, что висит на портах, и убить лишнее?
Набираем "netstat -aon" в консоли, где находим нужный порт и PID - идентификатор процесса. Затем открываем диспетчер задач - "Подробности". В колонке "идентификатор процесса" находим нужный ID. Теперь можно завершить процесс, если это требуется.
#сети
- Как определить, что висит на портах, и убить лишнее?
Набираем "netstat -aon" в консоли, где находим нужный порт и PID - идентификатор процесса. Затем открываем диспетчер задач - "Подробности". В колонке "идентификатор процесса" находим нужный ID. Теперь можно завершить процесс, если это требуется.
#сети
React. Раунд 2!
Готовлюсь ко внутреннему собеседованию по фронту. А значит, время нам с вами повторить пройденное!
- JSX-сущность = результат вызова функции createElement = объект с полями props, children етц.
Если держать в голове этот факт, не забудешь, что вообще такое хреновы пропсы.
- Children - это, если очень грубо, все, что между тегами элемента. <h1> -> тут children <- </h1). Это просто потомки, как в HTML.
- Еще внутри объекта есть key, ref, _owner и не только.
- Корневых узлов может быть несколько.
- Компоненты иммутабельны. То есть, для того, чтобы изменить изображение на экране, нужно перерисовать компонент целиком. Инсертнуть по-быстрому, как в классической верстке, нельзя.
- Обновляется только то, что изменилось. Внутри реакта сравниваются версии элемента "до и после", после чего обновляется только то, что изменилось.
#React
Готовлюсь ко внутреннему собеседованию по фронту. А значит, время нам с вами повторить пройденное!
- JSX-сущность = результат вызова функции createElement = объект с полями props, children етц.
Если держать в голове этот факт, не забудешь, что вообще такое хреновы пропсы.
- Children - это, если очень грубо, все, что между тегами элемента. <h1> -> тут children <- </h1). Это просто потомки, как в HTML.
- Еще внутри объекта есть key, ref, _owner и не только.
- Корневых узлов может быть несколько.
- Компоненты иммутабельны. То есть, для того, чтобы изменить изображение на экране, нужно перерисовать компонент целиком. Инсертнуть по-быстрому, как в классической верстке, нельзя.
- Обновляется только то, что изменилось. Внутри реакта сравниваются версии элемента "до и после", после чего обновляется только то, что изменилось.
#React
- Композиция в React - просто дробление UI на блоки. Больше блок - больше отдельных компонентов. Профит - переиспользуемость.
- Нельзя менять state в обход сеттера setState.
- Нельзя обновлять state с помощью props передачей объекта. Это потому, что state и props обновляются асинхонно, передаваемое значение может быть при этом потеряно. Нужно передавать в сеттер функцию.
- Можно обновлять поля state независимо в отдельных вызовах.
- Вообще state - это как props, только инкапсулированный. Работать со стейтом может исключительно компонент, которому он принадлежит.
- Состояние может быть передано дочерним компонентам. На этом принципе строится архитектура приложений Реакта: данные передаются только от родительских компонентов к дочерним, сверху вниз.
- Синтетическое событие - это обертка Реакта над стандартными событиями DOM. Используется для кроссбраузерности. Его интерфейс аналогичен стандартным событиям, имеется доступ и к оригинальным.
- Как передать аргумент в обработчик события? Поместить его в функцию-стрелку.
#React
- Нельзя менять state в обход сеттера setState.
- Нельзя обновлять state с помощью props передачей объекта. Это потому, что state и props обновляются асинхонно, передаваемое значение может быть при этом потеряно. Нужно передавать в сеттер функцию.
- Можно обновлять поля state независимо в отдельных вызовах.
- Вообще state - это как props, только инкапсулированный. Работать со стейтом может исключительно компонент, которому он принадлежит.
- Состояние может быть передано дочерним компонентам. На этом принципе строится архитектура приложений Реакта: данные передаются только от родительских компонентов к дочерним, сверху вниз.
- Синтетическое событие - это обертка Реакта над стандартными событиями DOM. Используется для кроссбраузерности. Его интерфейс аналогичен стандартным событиям, имеется доступ и к оригинальным.
- Как передать аргумент в обработчик события? Поместить его в функцию-стрелку.
#React
Привязка контекста в React
В компонентах-классах мы передаем обработчики событий в дочерние компоненты. Однако они не выполняются.
Что происходит?
Передавая метод класса в render, мы выполняем примерно следующее:
Как этого избежать?
Жестко привязать контекст метода к объекту. Для этого используем .bind(), стрелочные функции или замыкания. Старый добрый способ - привязать this в конструкторе:
Подробнее: https://learn-reactjs.ru/faq/passing-functions-to-components
#React
В компонентах-классах мы передаем обработчики событий в дочерние компоненты. Однако они не выполняются.
Что происходит?
Передавая метод класса в render, мы выполняем примерно следующее:
const newMethod = obj.method
Представим, что метод возвращает что-то вроде "this.something". Что такое this? Это ссылка на контекст объекта. Когда мы присваиваем метод внешней переменной, то и контекст меняем тоже.Как этого избежать?
Жестко привязать контекст метода к объекту. Для этого используем .bind(), стрелочные функции или замыкания. Старый добрый способ - привязать this в конструкторе:
this.methodName = this.methodName.bind(this)
.Подробнее: https://learn-reactjs.ru/faq/passing-functions-to-components
#React
Про Тайпскрипт
Типы указываются после имени переменной или перед {} для функций через двоеточие. Логика проста: именуем сущность и указываем, что возвращает.
Какие бывают типы:
- Примитивные: строки, целые числа, числа с запятой, булевы...
- Составные из нескольких примитивов: number | string
- Массивы, объекты и т.д.
- Кастомные (алиасы):
- Null и undefined
- функция при описании интерфейсов: ()
Интерфейсы
Это схематическое типирование обязательных и необязательных полей объекта. Пример:
Прочтем построчно поля объекта:
1. неизменяемое обязательное поле "столешница"
2. обязательное поле "ножки стола"
3. необязательное (знак вопроса перед двоеточием) поле "скатерть"
Присвоить интерфейс можно тремя способами:
Интерфейсы могут наследоваться:
Также можно описать сразу все типы полей объекта по ключу:
Типы указываются после имени переменной или перед {} для функций через двоеточие. Логика проста: именуем сущность и указываем, что возвращает.
Какие бывают типы:
- Примитивные: строки, целые числа, числа с запятой, булевы...
- Составные из нескольких примитивов: number | string
- Массивы, объекты и т.д.
- Кастомные (алиасы):
Login = string | undefined;
const login: Login = ...
- Для функций: любой примитив, либо Never (функция никогда не доходит до return), либо void (ничего не возвращает).- Null и undefined
- функция при описании интерфейсов: ()
Интерфейсы
Это схематическое типирование обязательных и необязательных полей объекта. Пример:
interface Table {
readonly countertop: boolean
tableLegs: number
tablecloth?: string
}
Далее интерфейс присваивается объекту, и тот может быть определен только по его схеме.Прочтем построчно поля объекта:
1. неизменяемое обязательное поле "столешница"
2. обязательное поле "ножки стола"
3. необязательное (знак вопроса перед двоеточием) поле "скатерть"
Присвоить интерфейс можно тремя способами:
- const obj: Interface = { ... }
(объект описывается)- const obj = {} as Interface;
(объект объявлен пустым)- const obj = <Interface>obj{}
(объект также пуст)Интерфейсы могут наследоваться:
interface Int2 extends Int1 {
...все поля Int1 под капотом...
getSum: () => number // обязательное поле-функция, возвращающее целое число
}
Также они могут описывать классы. Для этого используется ключевое слово implements:class Car implements ICar {
...обязательные поля класса...
}
Хорошая практика - называть интерфейсы с буквы I, как у Эпл, только с большой.Также можно описать сразу все типы полей объекта по ключу:
interface ICss = {
[key: string]: string...
}
#TypeScriptКоротко о Vue-Class-Component:
- Computed properties определяются как геттеры и сеттеры класса:
- Хуки и методы жизненного цикла можно определять как простые методы.
- Хуки из vue router и другие не из коробки нужно регистрировать, желательно в отдельном файле, через
- Можно создавать кастомные декораторы:
- Возможно наследование через обычный ES6 синтаксис.
- Нельзя использовать функции-стрелки с this внутри и конструкторы. Вместо них используют обычные методы (вместо стрелок) и методы жизненного цикла. Почему нельзя? Конструктор вызывается под капотом компонента, собирая данные, если вызывать вручную - вызовется дважды:
#Vue #JS
- Computed properties определяются как геттеры и сеттеры класса:
// Declared as computed property getter
get name() {
return this.firstName + ' ' + this.lastName
}
- Хуки и методы жизненного цикла можно определять как простые методы.
- Хуки из vue router и другие не из коробки нужно регистрировать, желательно в отдельном файле, через
Component.registerHooks
.- Можно создавать кастомные декораторы:
@MyDecorator
method(arg)
- Возможно наследование через обычный ES6 синтаксис.
- Нельзя использовать функции-стрелки с this внутри и конструкторы. Вместо них используют обычные методы (вместо стрелок) и методы жизненного цикла. Почему нельзя? Конструктор вызывается под капотом компонента, собирая данные, если вызывать вручную - вызовется дважды:
// DO NOT do this. Use "created" lifecycle hook instead.
constructor() {
fetch('/posts.json')
.then(res => res.json())
.then(posts => {
this.posts = posts
})
}
#Vue #JS
Junior - Middle: внутреннее путешествие
Вопрос лычек, конечно, субъективен и разнится от компании к компании, но мысль этого поста - про самоощущение разработчика.
Меняется оно только с реальным опытом. Паззл складывается: ты "вдруг" начинаешь видеть целостную картину цикла производства. Ты понимаешь, зачем придумали ООП, паттерны проектирования, к чему кажущееся усложнение кода на крупных проектах. Не робеешь перед новыми проектами и технологиями - понимая, что их вводят для облегчения работы или поддержки. Эджайл теперь не пустой звук - ты можешь не любить его, но умеешь подстраиваться. На собеседованиях ты спокоен и уверен в своей ценности - что помогает проходить их.
В то же время, тебе есть куда расти. Организовывать команду ты еще не умеешь, да и не рвешься. Решения об архитектуре системы в целом принимают другие. Базовые и смежные знания все еще неполные - но теперь ты сам себе наставник и знаешь, чем заполнить пробелы.
Изучи паттерны проектирования. Освежи знания алгоритмов. Поработай с бэкендом, БД, другими языками. Осознай, почему другие языки - такие, какие они есть. И работай на реальных проектах. Твой переход начнется сам собой - неизбежно и удивительно.
Вопрос лычек, конечно, субъективен и разнится от компании к компании, но мысль этого поста - про самоощущение разработчика.
Меняется оно только с реальным опытом. Паззл складывается: ты "вдруг" начинаешь видеть целостную картину цикла производства. Ты понимаешь, зачем придумали ООП, паттерны проектирования, к чему кажущееся усложнение кода на крупных проектах. Не робеешь перед новыми проектами и технологиями - понимая, что их вводят для облегчения работы или поддержки. Эджайл теперь не пустой звук - ты можешь не любить его, но умеешь подстраиваться. На собеседованиях ты спокоен и уверен в своей ценности - что помогает проходить их.
В то же время, тебе есть куда расти. Организовывать команду ты еще не умеешь, да и не рвешься. Решения об архитектуре системы в целом принимают другие. Базовые и смежные знания все еще неполные - но теперь ты сам себе наставник и знаешь, чем заполнить пробелы.
Изучи паттерны проектирования. Освежи знания алгоритмов. Поработай с бэкендом, БД, другими языками. Осознай, почему другие языки - такие, какие они есть. И работай на реальных проектах. Твой переход начнется сам собой - неизбежно и удивительно.
Правила хорошего тона в тестовых заданиях
Перед тем, как начать выполнять тестовое:
- Возникли вопросы, двусмысленные моменты? Обсуди с контактом в компании. Даже мелочи. Даже если придется писать через HR. Это важный момент софт-скиллз.
Перед отправкой кода проверь на:
- console.log и другие элементы дебага
- неиспользуемые переменные и стили
- неиспользуемые импорты
- любые другие хвосты и косяки
Написал README - проверь, чтобы описанные в нем методы или команды работали, как написано.
Можешь скачать свой проект из гитхаба отдельным экземпляром, установить и запустить. Многие забытые ошибки заметны на этом этапе.
Если их заметит уже проверяющий, плюсов тебе это не добавит.
Короче говоря - встречают по одёжке, даже тестовые задания. Неряшливый код ничем не лучше трехдневной щетины и запаха пота.
#softskills #собеседования
Перед тем, как начать выполнять тестовое:
- Возникли вопросы, двусмысленные моменты? Обсуди с контактом в компании. Даже мелочи. Даже если придется писать через HR. Это важный момент софт-скиллз.
Перед отправкой кода проверь на:
- console.log и другие элементы дебага
- неиспользуемые переменные и стили
- неиспользуемые импорты
- любые другие хвосты и косяки
Написал README - проверь, чтобы описанные в нем методы или команды работали, как написано.
Можешь скачать свой проект из гитхаба отдельным экземпляром, установить и запустить. Многие забытые ошибки заметны на этом этапе.
Если их заметит уже проверяющий, плюсов тебе это не добавит.
Короче говоря - встречают по одёжке, даже тестовые задания. Неряшливый код ничем не лучше трехдневной щетины и запаха пота.
#softskills #собеседования
Что спросить на собеседовании?
Знакомый из чата рассказал, что в первый же день на новой работе на него посыпались таски со сроками - времени войти в проект не дали. Непорядок, а? Это вдохновило меня собрать список вопросов, которые жизненно важно задать на собеседовании.
#1. Какой срок даете на то, чтобы вникнуть в проект, прежде чем начнутся "боевые" задачи?
#2. Онбординг - своими силами или есть человек, к которому можно обращаться и которому это не в тягость?
#3. Если не подойдем друг другу в испытательный, как это отразится на трудовой?
#4. Оформляете в белую?
Пишите в комментах свои пункты.
#собеседования #softskills
Знакомый из чата рассказал, что в первый же день на новой работе на него посыпались таски со сроками - времени войти в проект не дали. Непорядок, а? Это вдохновило меня собрать список вопросов, которые жизненно важно задать на собеседовании.
#1. Какой срок даете на то, чтобы вникнуть в проект, прежде чем начнутся "боевые" задачи?
#2. Онбординг - своими силами или есть человек, к которому можно обращаться и которому это не в тягость?
#3. Если не подойдем друг другу в испытательный, как это отразится на трудовой?
#4. Оформляете в белую?
Пишите в комментах свои пункты.
#собеседования #softskills
Центр вселенной
В разработке нужно понимать один простой принцип:
Программирование - это работа над данными.
Данные - или стейт - центр вселенной. Всё остальное подчиняется данным: обрабатывает, доставляет потребителю... View отрисовывает данные, Model - описывает их, и так далее.
От этого нужно начинать разработку. В изучении фреймворков надо разделять в голове их части на те, что работают с данными, и многочисленные обработчики. Так понять фреймворк проще, чем воспринимая кашей из чужеродного API. И уж тем более проще понять state manager'ы, подходя так к этому вопросу.
Задача фронтендера, таким образом, максимально быстро доставить данные пользователю.
Из этого вытекает еще одна мысль: одна из главных задач в вебе - оптимизация. Именно поэтому мы должны изучать алгоритмы, понимать O-нотацию, использовать лучшие практики.
В разработке нужно понимать один простой принцип:
Программирование - это работа над данными.
Данные - или стейт - центр вселенной. Всё остальное подчиняется данным: обрабатывает, доставляет потребителю... View отрисовывает данные, Model - описывает их, и так далее.
От этого нужно начинать разработку. В изучении фреймворков надо разделять в голове их части на те, что работают с данными, и многочисленные обработчики. Так понять фреймворк проще, чем воспринимая кашей из чужеродного API. И уж тем более проще понять state manager'ы, подходя так к этому вопросу.
Задача фронтендера, таким образом, максимально быстро доставить данные пользователю.
Из этого вытекает еще одна мысль: одна из главных задач в вебе - оптимизация. Именно поэтому мы должны изучать алгоритмы, понимать O-нотацию, использовать лучшие практики.
Место структур данных в программировании
Изучать структуры данных, пока не умеешь отделять в уме данные от остальных элементов кода, бессмысленно. Изучать их для галочки, зубрить для собесов - бессмысленно.
Построим осмысленную логическую цепочку.
Данные - это отдельный, обособленный и главный элемент разработки.
Чтобы обрабатывать данные, существуют алгоритмы.
Эффективность алгоритмов зависит от формы данных. Например, связанный список эффективен, когда нужно получить данные с начала или конца списка (O1), а бинарное дерево эффективнее для поиска вглубь, так как отсекает по половине данных за каждую итерацию.
Таким образом, структуры данных служат для упорядочивания данных, чтобы эффективно выполнять бизнес-задачи. А алгоритмы, в свою очередь, изучаются как правильные инструменты обработки этих структур.
Изучать структуры данных, пока не умеешь отделять в уме данные от остальных элементов кода, бессмысленно. Изучать их для галочки, зубрить для собесов - бессмысленно.
Построим осмысленную логическую цепочку.
Данные - это отдельный, обособленный и главный элемент разработки.
Чтобы обрабатывать данные, существуют алгоритмы.
Эффективность алгоритмов зависит от формы данных. Например, связанный список эффективен, когда нужно получить данные с начала или конца списка (O1), а бинарное дерево эффективнее для поиска вглубь, так как отсекает по половине данных за каждую итерацию.
Таким образом, структуры данных служат для упорядочивания данных, чтобы эффективно выполнять бизнес-задачи. А алгоритмы, в свою очередь, изучаются как правильные инструменты обработки этих структур.
Концепции фронтенда: повторяем главное
Давайте пройдемся по мета-уровню разработки интерфейсов. Что? Для чего? Зачем? Понимая это, мы сможем лучше понять сферу "как", то есть, конкретных реализаций.
- Из чего вообще состоит работа фронтенд-разработчика?
1. Пишем программный интерфейс для получения, обработки и отправки данных с бэкенда (CRUD).
2. Пишем визуальный интерфейс для вывода этих данных.
3. Добиваемся максимальной оптимизации с обеих сторон.
- Для чего нужны фронтенд-фреймворки?
1. Стандартизация. Фреймворки реализуют подход DRY: вводят универсальные решения для повторяющихся задач. Попутно это снимает с компаний необходимость писать велосипеды и обучать им новичков.
2. Компонентный подход. Мы делим приложение на изолированные компоненты - и это снижает нагрузку на мозги. Ты держишь в уме только свой кусочек сложной системы.
- Что такое реактивность?
Грубо говоря, это способность систем реагировать на изменение стейта приложения.
- Зачем нужен Vuex/Redux?
Vuex выносит объект данных - стейт - в отдельный стор, который прокидывается глобально и распределяется на отдельные модули. Это сделано для облегчения поддержки сложных систем. Также стейт-менеджер обеспечивает надежность работы с данными: мутировать их можно только с помощью внутренних методов стейт-менеджера, либо нельзя вовсе (данные не мутируются, а подменяются новыми на основе старых).
Давайте пройдемся по мета-уровню разработки интерфейсов. Что? Для чего? Зачем? Понимая это, мы сможем лучше понять сферу "как", то есть, конкретных реализаций.
- Из чего вообще состоит работа фронтенд-разработчика?
1. Пишем программный интерфейс для получения, обработки и отправки данных с бэкенда (CRUD).
2. Пишем визуальный интерфейс для вывода этих данных.
3. Добиваемся максимальной оптимизации с обеих сторон.
- Для чего нужны фронтенд-фреймворки?
1. Стандартизация. Фреймворки реализуют подход DRY: вводят универсальные решения для повторяющихся задач. Попутно это снимает с компаний необходимость писать велосипеды и обучать им новичков.
2. Компонентный подход. Мы делим приложение на изолированные компоненты - и это снижает нагрузку на мозги. Ты держишь в уме только свой кусочек сложной системы.
- Что такое реактивность?
Грубо говоря, это способность систем реагировать на изменение стейта приложения.
- Зачем нужен Vuex/Redux?
Vuex выносит объект данных - стейт - в отдельный стор, который прокидывается глобально и распределяется на отдельные модули. Это сделано для облегчения поддержки сложных систем. Также стейт-менеджер обеспечивает надежность работы с данными: мутировать их можно только с помощью внутренних методов стейт-менеджера, либо нельзя вовсе (данные не мутируются, а подменяются новыми на основе старых).
Неотвеченное с собеседований
Большую часть я просто не смог вспомнить, а кое-что не использовал.
Итак...
- Как сравнить два объекта?
Проще и современнее всего - через Object.is(obj1, obj2).
Cтарый способ - привести оба объекта к JSON и выполнить строгое сравнение.
- Для чего нужны атрибуты asynс и defer в теге <script>?
Оба атрибута делают загрузку кода неблокирующей. То есть, DOM загружается независимо от JS в файле.
async - полностью независимая загрузка кода.
defer - загрузка кода после загрузки контента, до события DOMContentLoaded.
Можно использовать вместе для поддержки старых браузеров (defer)
Большую часть я просто не смог вспомнить, а кое-что не использовал.
Итак...
- Как сравнить два объекта?
Проще и современнее всего - через Object.is(obj1, obj2).
Cтарый способ - привести оба объекта к JSON и выполнить строгое сравнение.
- Для чего нужны атрибуты asynс и defer в теге <script>?
Оба атрибута делают загрузку кода неблокирующей. То есть, DOM загружается независимо от JS в файле.
async - полностью независимая загрузка кода.
defer - загрузка кода после загрузки контента, до события DOMContentLoaded.
Можно использовать вместе для поддержки старых браузеров (defer)
CORS
Рассказывать буду тезисно.
CORS - это система безопасности обмена данными.
CORS переводится как Cross-Origin Resource Sharing.
Смысл CORS. Смысл в том, чтобы ограничивать работу клиента со сторонними ресурсами. Отличаться могут протокол, домен или порт. Браузер отправляет заголовки с запросом разрешения на операцию. В зависимости от настроек на бэке он выполняет операцию или выбрасывает ошибку.
Роль для фронта. Как фронтендер, я не запоминаю заголовков CORS. Так как я знаю механизм в общих чертах, то в реальной практике сообщаю об ошибке бэкендеру и мы быстро решаем проблему.
Рассказывать буду тезисно.
CORS - это система безопасности обмена данными.
CORS переводится как Cross-Origin Resource Sharing.
Смысл CORS. Смысл в том, чтобы ограничивать работу клиента со сторонними ресурсами. Отличаться могут протокол, домен или порт. Браузер отправляет заголовки с запросом разрешения на операцию. В зависимости от настроек на бэке он выполняет операцию или выбрасывает ошибку.
Роль для фронта. Как фронтендер, я не запоминаю заголовков CORS. Так как я знаю механизм в общих чертах, то в реальной практике сообщаю об ошибке бэкендеру и мы быстро решаем проблему.
Инкапусляция на практике
Прогаем на уровне интерфейсов, а не реализации.
Это значит, что детали реализации нужно оборачивать в абстракции и выстраивать взаимодействие между ними.
Например, для API чата напишем класс MessageObesrver.
- Придумаем, как класс будет взаимодействовать с приложением: что возвращают публичные методы, какие аргументы принимают.
- Выделим приватные поля и методы, где напишем реализацию с помощью, например, SocketIO.
- Опишем публичные методы, которые будут с ней работать. В них не должно быть ничего от конкретной реализации - они должны дергать приватные поля и методы.
С таким классом мы сможем легко заменить библиотеку или подправить код реализации, не меняя ничего в приложении. Класс оказывается чёрным ящиком с неизменным интерфейсом.
В SOLID это - буква "D": dependency inversion principle (принцип инверсии зависимостей).
#инкапсуляция #паттерны #SOLID
Прогаем на уровне интерфейсов, а не реализации.
Это значит, что детали реализации нужно оборачивать в абстракции и выстраивать взаимодействие между ними.
Например, для API чата напишем класс MessageObesrver.
- Придумаем, как класс будет взаимодействовать с приложением: что возвращают публичные методы, какие аргументы принимают.
- Выделим приватные поля и методы, где напишем реализацию с помощью, например, SocketIO.
- Опишем публичные методы, которые будут с ней работать. В них не должно быть ничего от конкретной реализации - они должны дергать приватные поля и методы.
С таким классом мы сможем легко заменить библиотеку или подправить код реализации, не меняя ничего в приложении. Класс оказывается чёрным ящиком с неизменным интерфейсом.
В SOLID это - буква "D": dependency inversion principle (принцип инверсии зависимостей).
#инкапсуляция #паттерны #SOLID
Open Close principe
Еще один принцип проектирования - отделение изменяемых частей приложения от неизменяемых. Неизменяемая часть не должная изменяться, будучи полностью абстрактной. При этом она должна быть открыта к использованию в максимальном количестве сценариев.
Например, есть задача сделать модальное окно.
Разделим его на две условные части:
- Контейнер с полупрозрачным оверлеем
- Область контента
Создадим для контейнера отдельный компонент, который ничего не будет знать о контенте. Постараемся предусмотреть возможную модификацию: например, компонент будет принимать объект пропов с настройками прозрачности оверлея, размеров и положения на экране. Оставим его опциональным.
Создадим компонент контента и пробросим в модальное окно.
С такой архитектурой компонент модального окна будет легко переиспользован в проекте.
#паттерны #SOLID
Еще один принцип проектирования - отделение изменяемых частей приложения от неизменяемых. Неизменяемая часть не должная изменяться, будучи полностью абстрактной. При этом она должна быть открыта к использованию в максимальном количестве сценариев.
Например, есть задача сделать модальное окно.
Разделим его на две условные части:
- Контейнер с полупрозрачным оверлеем
- Область контента
Создадим для контейнера отдельный компонент, который ничего не будет знать о контенте. Постараемся предусмотреть возможную модификацию: например, компонент будет принимать объект пропов с настройками прозрачности оверлея, размеров и положения на экране. Оставим его опциональным.
Создадим компонент контента и пробросим в модальное окно.
С такой архитектурой компонент модального окна будет легко переиспользован в проекте.
#паттерны #SOLID
Принцип подстановки Барбары Лисков
Всю ночь раскидывал мозгами над этим принципом. И, кажется, понял. 💡
Он весь о наследовании. Не обязательно в терминологии ООП.
Любая сущность, которая является подтипом некоей более общей сущности, при подстановке на место расширяемой сущности должна работать так же, как и расширяемая сущность.
Для кода, использовавшего предыдущую сущность, ничего не должно измениться.
За пример во фронтенде можно взять кнопки в UI-ките. Мы создаем компонент кнопки, содержащий общие стили, а затем "наследуем" от него подвиды кнопок. При замене кнопок мы не должны перетряхивать весь код вокруг них. В идеале для кода окружения кнопок измениться не должно вообще ничего.
Другой пример - разработка API. Внезапно на этом слое понадобилось реализовать кэширование. Мы наследуемся от существующего класса, допиливаем функциональность, распространяем новый класс по системе... И ничего больше в ней не меняем. Методы API работают как раньше.
Строгость следования этому принципу - вопрос открытый.
#SOLID
Всю ночь раскидывал мозгами над этим принципом. И, кажется, понял. 💡
Он весь о наследовании. Не обязательно в терминологии ООП.
Любая сущность, которая является подтипом некоей более общей сущности, при подстановке на место расширяемой сущности должна работать так же, как и расширяемая сущность.
Для кода, использовавшего предыдущую сущность, ничего не должно измениться.
За пример во фронтенде можно взять кнопки в UI-ките. Мы создаем компонент кнопки, содержащий общие стили, а затем "наследуем" от него подвиды кнопок. При замене кнопок мы не должны перетряхивать весь код вокруг них. В идеале для кода окружения кнопок измениться не должно вообще ничего.
Другой пример - разработка API. Внезапно на этом слое понадобилось реализовать кэширование. Мы наследуемся от существующего класса, допиливаем функциональность, распространяем новый класс по системе... И ничего больше в ней не меняем. Методы API работают как раньше.
Строгость следования этому принципу - вопрос открытый.
#SOLID
Принцип разделения интерфейсов
Он же Interface segregation principle.
В чем его суть?
Зайду с двух сторон.
Представим код на TypeScript. Дана сущность "Юзер", делящаяся по возможностям на "Пользователь", "Модератора" и "Админа". Её описывает общий интерфейс, содержащий методы для всех подтипов. Но это не имеет смысла: реализуя этот интерфейс, пользователь должен будет содержать пустой метод возможности админа. Либо методы админа будут опциональными - что лишит типизацию строгости. Чтобы этого избежать, разделим "толстый" интерфейс на три более узких и прокинем все в сущность через логическое "или".
Интерфейс - это не только сущность TS. Это часть кода, выставленная наружу для использования. Плохой интерфейс предоставляет слишком много методов - раздувается бандл, увеличивается зависимость программы от этого кода. А хороший предоставляет минимально возможный интерфейс.
Принцип разделения интерфейсов, следовательно, о разделении кода и избавлении от лишних зависимостей.
#SOLID
Он же Interface segregation principle.
В чем его суть?
Зайду с двух сторон.
Представим код на TypeScript. Дана сущность "Юзер", делящаяся по возможностям на "Пользователь", "Модератора" и "Админа". Её описывает общий интерфейс, содержащий методы для всех подтипов. Но это не имеет смысла: реализуя этот интерфейс, пользователь должен будет содержать пустой метод возможности админа. Либо методы админа будут опциональными - что лишит типизацию строгости. Чтобы этого избежать, разделим "толстый" интерфейс на три более узких и прокинем все в сущность через логическое "или".
Интерфейс - это не только сущность TS. Это часть кода, выставленная наружу для использования. Плохой интерфейс предоставляет слишком много методов - раздувается бандл, увеличивается зависимость программы от этого кода. А хороший предоставляет минимально возможный интерфейс.
Принцип разделения интерфейсов, следовательно, о разделении кода и избавлении от лишних зависимостей.
#SOLID
Главная проблема программистов-самоучек
...и ее решение. Не окончательное, не для всех. Но тем не менее.
Проблема самоучек - непонятно, что учить. Люди теряются в безбрежном просторе технологий - и либо бросают, либо поступают на дорогие, не обязательно качественные курсы.
Но объем технологий вовсе не безграничен.
Каждая технология решает строго определенный скоуп задач. Примем за данность, что каждая из них имеет аналоги...
...и это снижает реальное разнообразие в несколько раз. Не нужно учить реакт, ангуляр, вью и свелте. Достаточно взять одно из решений. Ответив на вопрос, что технология делает, ты поймёшь, чем аналог лучше - и без труда переключишься.
Далее. Не нужно начинать с низкого уровня - начинайте с архитектуры веба. Сложите ее из ответов на предыдущие вопросы.
То, что я предлагаю дальше, подходит только визуалам. Если это про вас - применяйте.
Создайте в голове визуальную модель архитектуры веба. Разделите React и Redux, REST и HTTP, клиент и сервер... Осознайте, в какой из блоков модели входят те или иные технологии. Визуализируйте каждый блок отдельно, разделяя на подблоки. Масштабируйте вглубь, пока это имеет смысл.
Это станет прорывом в вашем самообучении.
Вы начнёте учиться осознанно. Сможете переключаться в изучении разных технологий, не теряя общей картины. Будете запоминать детали этих технологий намного ярче. Сможете без волнения проходить собеседования - вместо каши в голове появится строгая и ясная модель.
Попробуйте. Это изменит все.
...и ее решение. Не окончательное, не для всех. Но тем не менее.
Проблема самоучек - непонятно, что учить. Люди теряются в безбрежном просторе технологий - и либо бросают, либо поступают на дорогие, не обязательно качественные курсы.
Но объем технологий вовсе не безграничен.
Каждая технология решает строго определенный скоуп задач. Примем за данность, что каждая из них имеет аналоги...
...и это снижает реальное разнообразие в несколько раз. Не нужно учить реакт, ангуляр, вью и свелте. Достаточно взять одно из решений. Ответив на вопрос, что технология делает, ты поймёшь, чем аналог лучше - и без труда переключишься.
Далее. Не нужно начинать с низкого уровня - начинайте с архитектуры веба. Сложите ее из ответов на предыдущие вопросы.
То, что я предлагаю дальше, подходит только визуалам. Если это про вас - применяйте.
Создайте в голове визуальную модель архитектуры веба. Разделите React и Redux, REST и HTTP, клиент и сервер... Осознайте, в какой из блоков модели входят те или иные технологии. Визуализируйте каждый блок отдельно, разделяя на подблоки. Масштабируйте вглубь, пока это имеет смысл.
Это станет прорывом в вашем самообучении.
Вы начнёте учиться осознанно. Сможете переключаться в изучении разных технологий, не теряя общей картины. Будете запоминать детали этих технологий намного ярче. Сможете без волнения проходить собеседования - вместо каши в голове появится строгая и ясная модель.
Попробуйте. Это изменит все.
Решаем задачки. Имитация Promise.all
Имеется недописанная функция parallel. Она принимает массив функций и коллбэк, вызываемый, когда все функции будут обработаны. Возвращает она массив результатов функций - в той последовательности, в которой они были переданы. Это важно!
Нельзя писать код вне функции parallel. Нежелательно использовать промисы.
Вот код:
#задачи
Имеется недописанная функция parallel. Она принимает массив функций и коллбэк, вызываемый, когда все функции будут обработаны. Возвращает она массив результатов функций - в той последовательности, в которой они были переданы. Это важно!
Нельзя писать код вне функции parallel. Нежелательно использовать промисы.
Вот код:
function parallel(funcArray, doneAll) {Решение - в следующем посте.
}
var a = function(done) {
setTimeout(function() {
done('result a');
}, 300);
};
var b = function(done) {
setTimeout(function() {
done('result b');
}, 200);
};
parallel([a,b], function(results) {
console.log(results); // ['result a', 'result b']
});
#задачи