Ссылки №13

Сегодня совсем без ютубов:

«Избранные произведения Леонардо да Винчи»

Это книга с выдержками из записей Леонардо да Винчи и описанием его жизни.

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

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

Читать не надоедает, потому что в книге много тем. Вот небольшая часть, о технике и математике:

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

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

Покой — не частный случай движения. Наоборот, вещи движутся только тогда, когда «потревожены» в своем спокойствии. Вечного движения быть не может

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

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

Об опыте. Леонардо считает, что опыт — главное, на что стоит опираться при доказательствах. В своих книгах он часто ссылается на явления природы, которые доказывают его точку зрения:

Чистый опыт — вот истинный учитель

И хотя природа начинается с причин и кончает опытом, нам надобно идти путем обратным, то есть начинать с опыта и с ним изыскивать причину

Нет действия в природе без причины; постигни причину, и тебе не нужен опыт

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

О цитировании и авторитетах:

Кто спорит, ссылаясь на авторитет, тот применяет не свой ум, а скорее память

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

О природе, человеческом теле и круговороте веществ:

Ты видел здесь, с каким тщанием природа расположила нервы, артерии и вены в пальцах по бокам, а не посредине, дабы при работе как‑нибудь не укололись и не порезались они

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

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

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

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

О силе и движении:

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

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

Всякое природное действие совершается кратчайшим образом, и вот почему свободное падение тяжести совершается к центру мира, так как это — наиболее короткое расстояние между движущимся [телом] и самым низким местом вселенной

Свободно падающая тяжесть приобретает с каждой единицей движения единицу веса

Часто Леонардо почти формулирует физические законы:

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

О наблюдениях за птицами и полётах:

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

О коршуне читаем, что, когда он видит своих птенцов в гнезде слишком жирными, клюет он им их бока и держит без пищи

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

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

О музыке, скульптуре, живописи и перспективе:

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

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

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

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

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

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

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

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

Самый большой грех живописца — это делать лица похожими друг на друга; повторение поз — большой порок

Дым не образует очерченных теней, и его собственные границы тем менее отчетливы, чем они дальше от своей причины

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

Есть бумажная и электронная версии. Я читал электронную, у Лебедева она свёрстана отлично, можно брать :–)

Лекарство от сломанной обратной совместимости

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

Шаблоны спешат на помощь

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

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

Пример

Возьмём абстрактное приложение. У него есть состояние state, где в поле user хранится информация о пользователе.

class State {
  constructor(initialState) {
    this.state = {...initialState}
  }

  update(key, value) {
    this.state = {
      ...this.state,
      [key]: value
    }
  }

  get(key) {
    return this.state[key]
  }
}

const state = new State({user: {}})

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

fetch('/fetch/user.json')
  .then((response) =>
    response.json())
  .then((user) =>
    state.update('user', user))
  .catch(handleError)

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

{
  name: 'John',
  lastName: 'Doe',
  birthYear: 1981,
  city: 'Berlin'
}

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

{
  fullName: {
    name: 'John',
    lastName: 'Doe'
  },
  birthDate: {
    year: 1981
  },
  address: {
    city: 'Berlin',
    street: '1 Hasselhoff Lane'
  }
}

Если приложение живёт давно, то к полям user.name, user.birthYear, user.city уже привязаны какие‑то его части. Их может быть несколько, и править каждое — не вариант.

Как‑то подгонять структуру ответа в обработчике запроса тоже плохо. Информация о пользователе может запрашиваться не только здесь. Да и код обработчика запроса распухнет.

Поэтому лучше работать со структурой ответа где‑то в другом месте. Напишем адаптер:

class UserToStateAdapter {
  constructor(state) {
    this.state = state
  }

  update(serviceUser) {
    const {fullName, birthDate, address} = serviceUser
    const {name, lastName} = fullName
    const {year} = birthDate
    const {city} = address

    const clientUser = {
      name, 
      lastName, 
      birthYear:year, 
      city,
      address,
    } 

    this.state.update('user', clientUser)
  }
}

const userToStateAdapter = new UserToStateAdapter(state)

Используем:

fetch('/fetch/user.json')
  .then((response) =>
    response.json())
  .then((user) =>
    userToStateAdapter.update(user)
  .catch(handleError)

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

В жизни

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

На одном из проектов нам нужно было из двух списков построить два разных дерева. В одном списке — отправители, в другом — получатели. Нужно было сгруппировать данные по отправителям или получателям в зависимости от выбора пользователя:

Начальная структура данных Первый вариант дерева Второй вариант дерева

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

Но есть пара минусов

Например:

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

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

Чем хорош и когда использовать

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

Да, если новая структура в корне отличается от старой, то одним адаптером, скорее всего, уже не обойтись. Но для задач типа «опять они все поля переназвали» — самое то.

Почитать на тему:

Ссылки №12

Сегодня раньше, но больше:

Как я переписал свой сайт и почему

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

Но просто взять и переверстать главную страницу — мало. Нужно перенести все проекты и статьи из старой базы в новое место, поэтому я долго откладывал переделку. И чем дольше откладывал, тем больше сайт мозолил мне глаза: «ты ж фронтендер, а сайт у тебя 7‑летней давности».

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

Чего я хотел

Уйти от ЦМС. Это, может, и удобно для тех, кто не знает технологий, но я знаю. ЦМС — это лишняя прослойка между мной и публикацией статьи или проекта. Мне, в принципе, достаточно статического ХТМЛ‑сайта.

Хранить заметки и проекты в маркдауне. Сам ХТМЛ неудобен: теги — это лишние символы, которые также тормозят публикацию, мне хотелось чего‑то проще. Выбрал маркдаун: в нём можно и изображения вставить, и ссылки, и код.

Сделать шрифты больше. От старых шрифтов у меня болели глаза. Не в смысле мне шрифт не нравился, Гельветика норм — размер был мелким. Теперь набираю основной текст шрифтом в 18 пикселей.

Сделать сайт семантичным и доступным. Чем большему количеству пользователей доступен мой контент, тем лучше.

Оптимизировать скорость загрузки. Старый сайт загружался долго. Надоело, хотелось сделать ракету :–)

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

Шрифт

Начал с подбора шрифта. Для основного текста я хотел шрифт с засечками, для заголовков — гротеск, для кода — моноширинный. Выбрал семейство ПТ: они бесплатные, с нужными начертаниями. А на Маке они есть в системе, поэтому многим пользователям их не придётся загружать с сервера.

В топку ЦМС

От ЦМС я избавился, но проблемы с шаблонами остались. Я понимал, что мне нужна какая‑то система сборки, которая бы брала мои заметки, шаблоны, мета‑информацию о странице и склеивала из них ХМТЛ‑страницы.

Сделал сборщик на Галпе. Он берёт джейсон со структурой, и по нему строит дерево сайта. На выходе получатеся статический ХМТЛ‑сайт.

Но мне хотелось оставить все старые ссылки рабочими, а заморачиваться с редиректами на новые страницы не хотелось. Поэтому взял старые ссылки и уже по ним построил дерево. Так ссылка /blog/ — превратилась в файл /blog/index.html

Старый адрес совпадает с новой структурой — 1

А /blog/page/ — в /blog/page/index.html.

Старый адрес совпадает с новой структурой — 2  С проектами так же. Работает, ничего дополнительно писать не надо — то, что нужно.

Технологии

Использовал только ХТМЛ, ЦСС, джаваскрипт. Как же здорово писать сразу работающий код, вместо настройки окружения, транспайлинга, компиляции и чего угодно ещё.

Использовал прогрессивное улучшение для кода. Например, стили у меня разбиты по разным файлам, а в главный файл я их подключаю стандартным ЦСС‑импортом. Плюс в том, что стили работают без сборки проекта. После сборки это один файл со всеми стилями, до — файл с импортами. В итоге что‑то быстро посмотреть и поправить я могу, не пересобирая сайт.

Чтобы страницы загружались быстрее, решил использовать оптимизированные форматы графики. Выбрал .webp, .jp2 и .jpx, которые подключаю через picture. Это помогло сократить трафик для Хрома в 10 раз, для Сафари примерно в 2 раза. Кроме разных форматов использую разные изображения для ретины и неретины, что тоже сокращает трафик для неретиновых экранов на 30–40%.

Дальше — больше :–) Одной оптимизации графики мне было мало. Я хотел, чтобы пользователям вообще приходилось как можно меньше загружать данных из интернета. Поэтому переехал на ХТТПС и подключил сервис‑воркер. Стили, скрипты, некоторые изображения — всё это сохраняется на устройстве пользователя. Тем, у кого сервис‑воркер уже работает, это сильно сокращает время загрузки и экономит трафик.

Семантика и доступность

Старый сайт страдал диватозом. Каждый раз, когда я слушал подкаст веб‑стандартов, мне становилось стыдно. Я, конечно, использовал section и nav, но на этом всё заканчивалось. Структура заголовков страдала, микроразметки не было, списки были не всегда списками.

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

В бою

Пока разрабатывал новый сайт, выпустил несколько заметок и один проект на старом. Обновлять заметки и проекты на новом оказалось проще. Никаких паролей и админок: пуш в мастер, оно улетело, обновилось. Для меня как разработчика это идеально.

Итог

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

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

Раньше ↓