├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── README.md ├── bundler └── extrarnalLinks.js ├── mustread.md ├── package.json ├── postcss.config.js ├── posthtml.config.js ├── pug.config.js ├── src ├── custom-media.css ├── favicons │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── fonts │ ├── steinbeck-italic.woff │ ├── steinbeck-italic.woff2 │ ├── steinbeck-regular.woff │ └── steinbeck-regular.woff2 ├── interactive │ ├── addBodyClickHandler.js │ └── index.js ├── mixin │ └── head.pug ├── pages │ ├── embedded.pug │ └── index.pug └── styles.css ├── stylelint.config.js └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | last 2 versions 2 | not dead 3 | not ie 11 4 | not ie_mob 11 5 | not op_mini all 6 | not op_mob > 0 7 | not and_qq > 0 8 | not android > 0 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: './node_modules/@solid-soda/scripts/config/eslint-js.js', 3 | }; 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .cache 3 | dist 4 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mustread 2 | 3 | Список хороших книг о разработке программ. 4 | + [Читать на сайте](https://read.kamyshev.me) 5 | + [Читать на GitHub](./mustread.md) 6 | 7 | ## Как добавить книгу 8 | + [Открой ишью с предложением](https://github.com/igorkamyshev/mustread/issues/new) 9 | + Обсуди целесообразность 10 | + Форкни репозиторий 11 | + Добавь книгу 12 | + Сделай пулл-реквест 13 | + Наслаждайся 14 | 15 | ## Разработка 16 | 17 | Проект использует менеджер пакетов `yarn`. Развернуть сайт в дев-режиме можно так: 18 | ``` 19 | git clone git@github.com:igorkamyshev/mustread.git 20 | yarn 21 | yarn dev 22 | ``` 23 | 24 | Проект использует [Prettier](https://prettier.io) и линтеры ([ESLint](https://eslint.org) и [Stylelint](https://stylelint.io)): 25 | ``` 26 | yarn s pretty 27 | yarn s lint --fix 28 | ``` 29 | 30 | Мы придерживаемся [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) для сообщений к коммитам. Чтобы легко сгенерировать сообщение по всем правилам есть специальная команда: 31 | ``` 32 | yarn s cz 33 | ``` 34 | 35 | ## Деплой 36 | 37 | Сайт автоматически деплоится в [Netlify](http://netlify.com/), на каждый пулл-реквест создается деплой-превью, где можно посмотреть как правка будет выглядеть на живом сайте. 38 | 39 | Собрать сайт для продакшна можно так: 40 | ``` 41 | git clone git@github.com:igorkamyshev/mustread.git 42 | yarn 43 | yarn build 44 | ``` 45 | -------------------------------------------------------------------------------- /bundler/extrarnalLinks.js: -------------------------------------------------------------------------------- 1 | module.exports.extrarnalLinks = tree => 2 | tree.match({ tag: 'a' }, i => ({ 3 | tag: 'a', 4 | content: i.content, 5 | attrs: { 6 | ...i.attrs, 7 | target: '_blank', 8 | rel: 'noopener', 9 | }, 10 | })); 11 | -------------------------------------------------------------------------------- /mustread.md: -------------------------------------------------------------------------------- 1 | ### Чистый код. Создание, анализ и рефакторинг 2 | Роберт Мартин, *Clean Code: A Handbook of Agile Software Craftsmanship* 3 | 4 | Эта книга о хорошем программировании. Она полна реальных примеров кода. Вы научитесь отличать хороший код от плохого, узнаете, как писать хороший код и как преобразовать плохой код в хороший. 5 | 6 | В первой части излагаются принципы, паттерны и приемы написания чистого кода; приводится много примеров. Вторая часть состоит из практических сценариев. Каждый сценарий представляет собой упражнение по чистке кода или преобразованию проблемного кода в код с меньшим количеством проблем. Третья часть книги — перечнень эвристических правил и «запахов кода». 7 | 8 | ### Путь программиста 9 | Джон Сонмез, *Soft Skills: The Software Developer’s Life Manual* 10 | 11 | Исчерпывающая инструкция о жизни программиста: что требуется для выстраивания успешной карьеры программиста, помогает лучше понять профессию и коллег, оставаться востребованным на рынке труда, целенаправленно и результативно развиваться, получать от любимой работы подлинное удовольствие. 12 | 13 | ### Теоретический минимум по Computer Science. Все что нужно программисту и разработчику 14 | Владстон Феррейра Фило, *Computer Science Distilled: Learn the Art of Solving Computational Problems* 15 | 16 | В этой книге рассматриваются базовые темы компьютерных наук: сложность алгоритмов, комбинаторика, теория вероятностей, устройство баз данных, архитектура компьютеров. Это необязательно для написания программ, но профессиональному разработчику требуется понимать, как работает тот код, который он создает. 17 | 18 | ### Идеальный программист. Как стать профессионалом разработки ПО 19 | Роберт Мартин, *The Clean Coder: A Code of Conduct for Professional Programmers* 20 | 21 | Дядюшка Боб, рассказывает о том, что значит «быть профессиональным программистом», описывая методы, инструменты и подходы разработки «идеального ПО». Книга насыщена практическими советами в отношении разных аспектов программирования: от оценки проекта и написания кода до рефакторинга и тестирования. Эта книга – больше, чем описание методов, она о профессиональном подходе к процессу разработки. 22 | 23 | ### Программист-фанатик 24 | Чад Фаулер, *Passionate Programmer* 25 | 26 | Книга представляет собой сборник практических советов и рекомендаций, касающихся ситуаций, с которыми сталкиваются разработчики: отсутствие мотивации, выбор приоритетов, психология программирования, отношения с руководством и коллегами. 27 | 28 | ### Чистая архитектура. Искусство разработки программного обеспечения 29 | Роберт Мартин, *Clean Architecture. A Craftsman’s Guide to Software Structure and Design* 30 | 31 | Дядюшка Боб дает прямые и лаконичные ответы на ключевые вопросы архитектуры и дизайна. В этой книге нет нескольких вариантов в стиле «решай сам», она объясняет, что делать, по какой причине и почему именно такое решение станет принципиально важным для спокойной разработки приложения. 32 | 33 | ### Семь языков за семь недель. Практическое руководство по изучению языков программирования 34 | Брюс Тейт, *Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages* 35 | 36 | Вместе с семью языками программирования вы исследуете важные современные модели программирования. Познакомитесь с динамической типизацией, которая делает языки Ruby, Python и Perl такими гибкими. Постигнете систему прототипов, лежащую в основе языка JavaScript. Увидите, как сопоставление с образцом в языке Prolog сказалось на формировании языков Scala и Erlang. Узнаете, чем функциональное программирование на языке Haskell отличается от программирования на языках семейства Lisp, включая Clojure. 37 | 38 | ### Проект «Феникс». Роман о том, как DevOps меняет бизнес к лучшему 39 | Джордж Спаффорд, Кевин Бер, *The Phoenix Project: A Novel about It, Devops, and Helping Your Business Win* 40 | 41 | Это книга о том, почему DevOps-практики критически важны для бизнеса. Она показывает, насколько важна интеграция разработки и эксплуатации, в чем настоящая ценность программного обеспечения и как эту ценность извлекать. 42 | 43 | ### Предметно-ориентированное проектирование (DDD). Структуризация сложных программных систем 44 | Эрик Эванс, *Domain-Driven Design: Tackling Complexity in the Heart of Software* 45 | 46 | Книга рассказывает о систематическом предметно-ориентированном подходе. В ней представлен широкий набор приемов и методик, фундаментальных принципов, помогающих в реализации программных проектов из сложных предметных областей. 47 | 48 | В книге рассказывается, как с помощью модели предметной области придать разработке сложной системы нужное направление и динамику. Выделены основные приемы и образцы-шаблоны, образующие общий язык группы разработчиков. Рассказывается о необходимости рефакторинга не только кода, но и модели в его основе, что приводит к углублению знаний о предметной области и повышению качества взаимодействия между специалистами и программистами. 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mustread", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "repository": "git@github.com:igorkamyshev/mustread.git", 6 | "author": "Igor Kamyshev ", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev": "concurrently --kill-others \"parcel src/pages/index.pug\" \"parcel watch src/pages/embedded.pug\"", 10 | "build": "parcel build src/pages/*", 11 | "s": "yarn soda" 12 | }, 13 | "dependencies": {}, 14 | "devDependencies": { 15 | "@solid-soda/scripts": "^1.15.2", 16 | "autoprefixer": "^9.7.4", 17 | "concurrently": "^5.0.2", 18 | "marked": "^0.8.0", 19 | "parcel-bundler": "^1.12.4", 20 | "postcss-color-mod-function": "^3.0.3", 21 | "postcss-custom-media": "^7.0.8", 22 | "postcss-nesting": "^7.0.1", 23 | "postcss-scrollbar": "^0.3.0", 24 | "pug": "^2.0.4" 25 | }, 26 | "husky": { 27 | "hooks": { 28 | "pre-commit": "yarn soda lint-staged", 29 | "pre-push": "yarn soda lint", 30 | "commit-msg": "yarn soda commitlint" 31 | } 32 | }, 33 | "publishConfig": { 34 | "access": "public" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer'), 4 | require('postcss-nesting'), 5 | require('postcss-custom-media')({ 6 | importFrom: './src/custom-media.css', 7 | }), 8 | require('postcss-scrollbar'), 9 | require('postcss-color-mod-function'), 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /posthtml.config.js: -------------------------------------------------------------------------------- 1 | const { extrarnalLinks } = require('./bundler/extrarnalLinks'); 2 | 3 | module.exports = { 4 | plugins: [extrarnalLinks], 5 | }; 6 | -------------------------------------------------------------------------------- /pug.config.js: -------------------------------------------------------------------------------- 1 | const { readFileSync } = require('fs'); 2 | const { join } = require('path'); 3 | 4 | const LIST_PATH = 'mustread.md'; 5 | 6 | const mustread = readFileSync(join(__dirname, LIST_PATH)).toString(); 7 | 8 | module.exports = { 9 | locals: { 10 | mustread, 11 | md: require('marked'), 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /src/custom-media.css: -------------------------------------------------------------------------------- 1 | /* custom media queries */ 2 | @custom-media --phoneDown (max-width: 839px); 3 | @custom-media --phoneUp (min-width: 840px); 4 | 5 | @custom-media --smallPhoneDown (max-width: 399px); 6 | @custom-media --smallPhoneUp (min-width: 400px); 7 | -------------------------------------------------------------------------------- /src/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/favicons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/favicons/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /src/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /src/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /src/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/favicons/favicon.ico -------------------------------------------------------------------------------- /src/favicons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/favicons/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mustread List", 3 | "short_name": "mustread", 4 | "icons": [ 5 | { 6 | "src": "./android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "./android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff" 18 | } 19 | -------------------------------------------------------------------------------- /src/fonts/steinbeck-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/fonts/steinbeck-italic.woff -------------------------------------------------------------------------------- /src/fonts/steinbeck-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/fonts/steinbeck-italic.woff2 -------------------------------------------------------------------------------- /src/fonts/steinbeck-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/fonts/steinbeck-regular.woff -------------------------------------------------------------------------------- /src/fonts/steinbeck-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-cemetery/mustread/9f5700e12f173668a6839bcc6555dda1361a5bbe/src/fonts/steinbeck-regular.woff2 -------------------------------------------------------------------------------- /src/interactive/addBodyClickHandler.js: -------------------------------------------------------------------------------- 1 | export const addBodyClickHandler = () => { 2 | document.addEventListener('click', () => { 3 | parent.postMessage('click-mustread', '*'); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /src/interactive/index.js: -------------------------------------------------------------------------------- 1 | import { addBodyClickHandler } from './addBodyClickHandler'; 2 | const bootstrap = () => { 3 | addBodyClickHandler(); 4 | }; 5 | 6 | try { 7 | bootstrap(); 8 | } catch (error) { 9 | document.addEventListener('DOMContentLoaded', bootstrap); 10 | } 11 | -------------------------------------------------------------------------------- /src/mixin/head.pug: -------------------------------------------------------------------------------- 1 | mixin head(interactive=false) 2 | title Mustread List | kamyshev.code 3 | 4 | link(rel='stylesheet', href='../styles.css') 5 | 6 | meta(name="viewport", content="width=device-width, initial-scale=1") 7 | meta(name="description" content="Невероятный список книг, которые стоит прочитать кажому разработчику") 8 | 9 | if interactive 10 | script(src='../interactive/index.js' defer) 11 | 12 | link(rel="apple-touch-icon" sizes="180x180" href="../favicons/apple-touch-icon.png") 13 | link(rel="icon" type="image/png" sizes="32x32" href="../favicons/favicon-32x32.png") 14 | link(rel="icon" type="image/png" sizes="16x16" href="../favicons/favicon-16x16.png") 15 | link(rel="manifest" href="../favicons/site.webmanifest") 16 | link(rel="mask-icon" href="../favicons/safari-pinned-tab.svg" color="#0000ff") 17 | link(rel="shortcut icon" href="../favicons/favicon.ico") 18 | meta(name="theme-color" content="#ffffff") 19 | -------------------------------------------------------------------------------- /src/pages/embedded.pug: -------------------------------------------------------------------------------- 1 | include ../mixin/head.pug 2 | 3 | html 4 | +head(true) 5 | body 6 | main(class="main embedded") 7 | != md(mustread) 8 | -------------------------------------------------------------------------------- /src/pages/index.pug: -------------------------------------------------------------------------------- 1 | include ../mixin/head.pug 2 | 3 | html 4 | +head() 5 | body 6 | main(class="main standalone") 7 | p.about Привет, меня зовут Игорь, веду канал в Телеграме kamyshev.code, делаю фронтенды в Aviasales и ещё много разных штук. Ниже список книг, которые, на мой взгляд, стоит прочесть каждому разработчику. Порядок имеет значение. 8 | 9 | != md(mustread) 10 | 11 | p(class="github") Ставьте звездочки и присылайте пулл-реквесты на GitHub 12 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* fonts */ 2 | @font-face { 3 | font-family: 'Steinbeck'; 4 | font-style: normal; 5 | font-weight: normal; 6 | src: url('./fonts/steinbeck-regular.woff2') format('woff2'), 7 | url('./fonts/steinbeck-regular.woff') format('woff'); 8 | font-display: swap; 9 | } 10 | 11 | @font-face { 12 | font-family: 'Steinbeck'; 13 | font-style: italic; 14 | font-weight: normal; 15 | src: url('./fonts/steinbeck-italic.woff2') format('woff2'), 16 | url('./fonts/steinbeck-italic.woff') format('woff'); 17 | font-display: swap; 18 | } 19 | 20 | :root { 21 | --color-primary: blue; 22 | --color-secondary: rgb(255, 59, 106); 23 | --main-font: 'Steinbeck', -apple-system, BlinkMacSystemFont, 24 | 'Apple Color Emoji', Arial, sans-serif; 25 | 26 | --header: 24px/110% var(--main-font); 27 | --subheader: 22px/110% var(--main-font); 28 | --text: 18px/125% var(--main-font); 29 | 30 | @media (--smallPhoneDown) { 31 | --header: 20px/110% var(--main-font); 32 | --subheader: 17px/110% var(--main-font); 33 | --text: 14px/125% var(--main-font); 34 | } 35 | } 36 | 37 | ::selection { 38 | color: white; 39 | background-color: color-mod(var(--color-secondary) alpha(0.99)); 40 | } 41 | 42 | * { 43 | box-sizing: border-box; 44 | scrollbar-color: transparent transparent; 45 | scrollbar-width: thin; 46 | 47 | /* not in standart, but so cute =) */ 48 | &::-webkit-scrollbar { 49 | width: 4px; 50 | padding-right: 10px; 51 | } 52 | 53 | &:hover { 54 | scrollbar-color: blue transparent; 55 | } 56 | } 57 | 58 | html { 59 | width: 100vw; 60 | overflow-x: hidden; 61 | } 62 | 63 | body { 64 | width: 100vw; 65 | margin: 0px; 66 | font-family: var(--main-font); 67 | } 68 | 69 | a { 70 | color: var(--color-primary); 71 | text-decoration: none; 72 | } 73 | 74 | .main { 75 | max-width: 670px; 76 | 77 | & > h3 { 78 | font: var(--header); 79 | margin-block-start: 40px; 80 | margin-block-end: 8px; 81 | 82 | &:first-of-type { 83 | margin-block-start: 8px; 84 | } 85 | } 86 | 87 | & > p { 88 | font: var(--text); 89 | margin-block-start: 8px; 90 | margin-block-end: 8px; 91 | } 92 | 93 | & > h3 + p { 94 | font: var(--subheader); 95 | margin-block-start: 12px; 96 | margin-block-end: 12px; 97 | } 98 | 99 | & > .github { 100 | margin-block-start: 68px; 101 | 102 | @media (--smallPhoneDown) { 103 | margin-block-start: 48px; 104 | } 105 | } 106 | 107 | & > .about { 108 | margin-block-end: 40px; 109 | } 110 | } 111 | 112 | .standalone { 113 | padding: 12px; 114 | 115 | @media (--phoneUp) { 116 | padding: 24px; 117 | } 118 | 119 | & > h3 { 120 | font: var(--header); 121 | margin-block-start: 40px; 122 | margin-block-end: 8px; 123 | } 124 | 125 | overflow: scroll; 126 | } 127 | 128 | .embedded { 129 | padding: 0 24px 60px 24px; 130 | } 131 | -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: './node_modules/@solid-soda/scripts/config/stylelint.js', 3 | }; 4 | --------------------------------------------------------------------------------