Архитектурные шаблоны вторичны

Не знаю как дела обстоят сейчас, но лет 5-7 назад на собеседованиях было ультра-модно спрашивать про архитектурные шаблоны. Абстрактные фабрики, синглтоны, вот это все. Возможно это и хорошая разминка для ума, но ведь архитектурные шаблоны - не самоцель. Они - средство. А цель - это адекватная архитектура приложения. Не супер-сложная (чтобы коллеги не приходили в ужас от количества реверансов и условностей при чтении/написании кода), не полное ее отсутствие (никто не любит big ball of mud катающийся в тарелке со спагетти), а сбалансированная (т.е. с умеренным использованием абстракций и инкапсуляции), симметричная (все компоненты примерно одного размера, нет god objects и армии анемичных недо-компонентов) и обладающая слабым зацеплением (aka loose coupling, обожаю российскую терминологию) структура программы.

Читать дальше

Контейнеры, контейнеры, контейнеры!

Термин container довольно сильно перегружен. Для разных людей и в зависимости от контекста он может означать разные вещи (systemd-nspawn, lxc/lxd, docker, rkt, OCI-complaint runtime, kata containers, etc). Но основная цель контейнеризации остается неизменной - это эффективная упаковка и изолированное выполнение пользовательских приложений, реализуемая на уровне операционной системы (а по факту - Linux). Эта идея и технология существует довольно давно, но по-настоящему популярной ей удалось стать именно благодаря удобной реализации от Docker.

Так хорошо всем знакомые docker build|push|pull|run позволили обычным смертными программистами воспользоваться всеми преимуществами контейнеризации без выполнения сложных последовательностей команд и тонкой конфигурации. Но, у такого коробочного решения оказалась и обратная сторона. Повседневное использование docker run -it ubuntu bash (или написание Dockerfile-ов, начинающихся с FROM centos) может привести к тому, что контейнер начнет казаться чем-то мало отличимым от полноценной операционной системы, спрятанной внутри некоторой коробочки виртуализации, созданной докером на вашем хосте.

Читать дальше

Пишем свой веб-сервер на Python: протокол HTTP

На данный момент мы умеем отправлять и принимать данные по сети и организовывать обработку запросов на сервере. Настало время перейти на более высокий уровень - реализовать свой HTTP сервер.

Для начала определимся, что же такое HTTP. Hypertext Transfer Protocol (HTTP) - это протокол прикладного уровня, предназначенный для передачи гипертекстовых данных в распределенных информационных системах. Ух, сложнааа... А на самом деле нет. Давайте разбираться!

Протокол - это не более, чем соглашение между двумя или более участниками некоторого взаимодействия. Когда речь идет о сетевом взаимодействии, протоколы принято условно разделять на уровни. В самом низу находятся протоколы физического уровня, определяющие как данные передаются в физических средах, т.е. по проводам, оптоволокну, и т.п. Знакомые нам из первой части протоколы IP и TCP - это протоколы сетевого и транспортного уровня, соответственно. Они определяют более высокоуровневые детали взаимодействия, в частности, IP отвечает за адресацию компьютеров/узлов в сети, а TCP - за надежную передачу данных произвольной (т.е. в общем случае превышающей размер одного IP-пакета) длины между узлами. HTTP же располагается на самом высоком уровне - прикладном. От нижележащих протоколов HTTP ожидает гарантий надежности доставки данных, а сам концентрируется на определении понятий запросов и ответов (сообщений) и их семантике. Фактически, HTTP является основным протоколом передачи данных в вебе, а сами данные являются гипертекстом, зачастую представленным в формате HTML-страниц.

Картинка для привлечения внимания (HTTP)

Читать дальше

9001 способ создать веб-сервер на Python

Дополняемый список способов запустить веб-сервер на Python:

Читать дальше

Пишем свой веб-сервер на Python: процессы, потоки и асинхронный I/O

В прошлой части мы познакомились с TCP-сокетами, как инструментом передачи данных по сети, основами их использования на стороне сервера и клиента. В этот раз речь пойдет про обработку запросов. Существует множество способов организации обработки запросов сервером: один клиент - один процесс, один клиент - один поток, много клиентов - один поток с асинхронным I/O, а также гибридные подходы. Мы рассмотрим основные моменты каждого из подходов, их достоинства и недостатки.

Картинка для привлечения внимания (логотип Python и кусочек редактора кода)

Читать дальше

Пишем свой веб-сервер на Python: сокеты

Что такое веб-сервер?

Начнем с того, что четко ответим на вопрос, что же такое веб-сервер?

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

Клиент общается с сервером по сети

Читать дальше

Наследование в JavaScript

Наследование - это один из способов повторного использования кода. Оно бывает двух типов: на основе классов (class-based) и прототипное (prototypal). В любом случае, так как речь про объектно-ориентированное программирование, наследование - это про создание множества объектов, обладающих общими свойствами, на основе уже существующих.

Читать дальше

Мастерить!

Есть два типа языков: языки, где есть только один очевидный/правильный путь реализовать что-либо (Python, Java), и языки, где одну и ту же фичу можно закодить тысячей и одним способом (C++, JavaScript, Ruby). Первые больше похожи на детские конструкторы, вторые - на пластелин.

Подробнее LEGOs, Play-Doh, and Programming и инфографика.

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

Читать дальше