├── .gitignore ├── Archive ├── Colonizer-demo.gif ├── Discord-roles.md ├── Intro-test-task.md └── Onboarding-way.md ├── Learn ├── Articles │ ├── Do-less-do-more │ │ ├── img │ │ │ ├── img-1.jpg │ │ │ ├── img-2.jpg │ │ │ └── img-3.jpg │ │ └── readme.md │ ├── How-to-dispose.md │ ├── Jinder │ │ ├── img │ │ │ ├── img-1.jpg │ │ │ ├── img-10.jpg │ │ │ ├── img-11.jpg │ │ │ ├── img-2.jpg │ │ │ ├── img-3.jpg │ │ │ ├── img-4.jpg │ │ │ ├── img-5.jpg │ │ │ ├── img-6.jpg │ │ │ ├── img-7.jpg │ │ │ ├── img-8.jpg │ │ │ └── img-9.jpg │ │ └── readme.md │ ├── Make-types-not-classes │ │ ├── img │ │ │ ├── img-1.jpg │ │ │ ├── img-2.jpg │ │ │ └── img-3.jpg │ │ └── make-types-not-classes.md │ ├── Starting-new-repository.md │ ├── Using-swagger-codegen.md │ └── Working-with-git │ │ ├── Diagrams │ │ ├── Git-branches-stage-1.puml │ │ └── Git-branches-stage-2.puml │ │ ├── Pictures │ │ ├── pic1.png │ │ ├── pic10.png │ │ ├── pic11.png │ │ ├── pic12.png │ │ ├── pic13.png │ │ ├── pic14.png │ │ ├── pic15.png │ │ ├── pic16.png │ │ ├── pic17.png │ │ ├── pic18.png │ │ ├── pic19.png │ │ ├── pic2.png │ │ ├── pic20.png │ │ ├── pic21.png │ │ ├── pic22.png │ │ ├── pic23.png │ │ ├── pic24.png │ │ ├── pic25.png │ │ ├── pic7.png │ │ └── pic8.png │ │ └── README.md ├── Books │ ├── Book-guide.puml │ └── Books.md └── Roadmap │ ├── Roadmap.md │ ├── roadmap.png │ └── roadmap.xmind ├── README.md └── logo.svg /.gitignore: -------------------------------------------------------------------------------- 1 | *.vpp.* -------------------------------------------------------------------------------- /Archive/Colonizer-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Archive/Colonizer-demo.gif -------------------------------------------------------------------------------- /Archive/Discord-roles.md: -------------------------------------------------------------------------------- 1 | # Discord roles 2 | 3 | Набросок какой-то недоматрицы компетентности для ролей. **In dev!** 4 | 5 | - Последователь 6 | - Написанное тестовое задание 7 | 8 | - Беженец Cyberforum'а 9 | - Теория: 10 | - Может объяснить и обсудить принятые в своем коде решения (по структуре кода) 11 | - Практика: 12 | - Умеет применять базовые инструменты дебага 13 | - Умеет работать с git - понимать что такое ветки, делать commit, использовать push/pull, 14 | - Умеет работать с nuget 15 | - Умеет самостоятельно решать минорные задачи в проекте по заранее написанным ишуям 16 | 17 | - Опытный юзер Метанита 18 | - Теория: 19 | - Может объяснить базовые принципы ООП (Абстракция, Инкапсуляция, Наследование, Полиморфизм). 20 | - Практика: 21 | - Умеет вести командную разработку на гитхабе используя pull request, issues, ветки 22 | - Имеет опыт самостоятельного ресерча и интеграции внешних компонент 23 | - Имеет опыт реализации фичей в рамках проектов 24 | 25 | - Жрец MS Docs 26 | - Практика: 27 | - Умеет проектировать компоненты решения в соответствии с Clean Code, паттерны, SOLID, DRY и т.д. 28 | - Умеет проектировать логическую модель данных, выделять сущности, аттрибуты, связи и реализовывать соответствующие системы 29 | - Имеет опыт использования базы данных в проекте в качестве хранилища данных 30 | - Может декомпозировать проблему на ряд задач, выстраивать процесс итеративной разработки 31 | - One of: 32 | - Может разбираться в решениях других участников команды, делать ревью, давать конструктивный фидбек 33 | - Имеет опыт проектирования и реализации функционала в рамках проектов 34 | 35 | - Оккультист 36 | - Теория: 37 | - Умеет принимать решения в рамках проектов, обосновывать их значимость, доносить до команды 38 | - Практика: 39 | - Имеет пример реализацию проекта, который демонстрирует интеграцию с внешними сервисами/управление данными, применение паттернов/бест практис, MVVM/MVC/etc. 40 | - One of: 41 | - Имеет опыт разработки UI с использованием C# фреймворков с применением MVVM 42 | - Имеет опыт разработки бекенда с использование ASP 43 | - One of: 44 | - Знает основы CI/CD 45 | - Знает про тестируемость кода, имеет опыт разработки тестируемого кода 46 | - Знает про внутренние механизмы C#, особенности реализации .NET 47 | 48 | - Адепт Рихтера 49 | - Теория: 50 | - Знает про внутренние механизмы C#, особенности реализации .NET 51 | - Понимание режимов синхронизаций, различия объектов синхронизаций, slim-версии, Async-await, дедлоки 52 | - Практика: 53 | - Умеет работать с многопоточным кодом 54 | - Имеет примеры разработанных архитектурных решений в проектах 55 | 56 | - Евангелист секты 57 | - Теория: 58 | - Знает про основы жизненного цикла разработки 59 | - Практика: 60 | - Спроектированное решение по которому выделены требования, составлено тз, выстроен процесс разработки 61 | - Софты: 62 | - Умеет выстраивать командный воркфлоу разработки 63 | - Умеет вести разработку проекта: разработка и обоснование требований, формирование и декомпозиция задач, делегированние, мониторинг 64 | - Уметь менторить сектантов, шейрить знания, делиться обратной связью, создавать и развивать комьюнити 65 | - Быть евангелистом, источником знаний, продвигать в массы правильные вещи 66 | - Желание (а не только возможность!) уделять секте n-ое количество времени. Понимать, что `быть источником знаний` это не ответить раз в месяц на пинг с вопросом -------------------------------------------------------------------------------- /Archive/Intro-test-task.md: -------------------------------------------------------------------------------- 1 | # Тестовое задание "Colonizer" 2 | 3 | Цель тестового задания - стать первым шагом сектанта в мир C#. В ходе его выполнения вы сможете закрепить свои знания о C# на практике. Полезную информацию для выполнения можно найти по ссылкам в нашей роадмапе - https://github.com/kysect/Main/blob/master/roadmap/csharp.md. 4 | 5 | Для отправки на ревью нужно создать репозиторий на гитхабе, загрузить в основную ветку пустой солюшен, а в отдельную ветку (назвать её можно произвольно, например, dev) загрузить решение и после этого отправить пул-реквест. Если вы мало знакомы с гитхабом, можно начать с [этого гайда](../articles/working-with-github/README.md). Когда задание будет выполнено, его будут ревьюить менторы секты, которые смогут дать фидбек и посоветовать изучить что-то дополнительно, чтобы закрыть пробелы в существующих знаниях. 6 | 7 | ## Glossary 8 | 9 | - Поле - прямоугольный участок консоли, который зарисовывается цветами в ходе работы приложения. 10 | - Пиксель - элемент поля. 11 | - Пространство - множество пикселей одинакового цвета, которые связаны между собой общей гранью или другим пикселем. 12 | 13 | ## Этап 1. Реализация отрисовки поля 14 | 15 | 1. Реализовать код для отрисовки поля. Поле состоит из множества пикселей, которые должны принимать случайный цвет; 16 | 2. Реализовать возможность задавать множество цветов, из которого выбирается случайный цвет; 17 | 3. Реализовать возможность задавать размер поля. 18 | 19 | Дополнительная информация: 20 | 21 | - При указании большого размера поля можно получить ошибку выхода за пределы консоли. Это связано с тем, что размер открытой консоли может быть меньше поля. Решить эту проблему можно, если указать ожидаемого размера консольного окна через `Console.SetWindowSize()` (работает только на Windows) или заранее растянуть окно консоли; 22 | - Доступные цвета для консоли определены в перечислении `ConsoleColor`, получить их список можно через `Enum.GetValues()`; 23 | - При работе со случайными значениями стоит использовать класс `Random`, но не нужно создавать его экземпляры - есть статическое поле `Random.Shared`; 24 | - В базовой библиотеке нет методов, которые позволяют рисовать пикели в консоли. Такую логику можно реализовать меняя цвет консоли (`Console.BackgroundColor = ConsoleColor.XXX`) и рисуя пробелы на этом цвете (`Console.Write(' ')`). Чтобы "очистить" консоль от текущего цвета, после отрисовки пробела нужно поставить знчение `Console.BackgroundColor` в исходный цвет консоли. Для отрисовки "пикселя" в конкретном месте есть метод `Console.SetCursorPosition(x, y)`, а для отчистки консоли - `Console.Clear()`. 25 | 26 | ## Этап 2. Введение пространств 27 | 28 | 1. Реализовать алгоритм поиска всех пространств на поле; 29 | 2. Реализовать логику поиска смежных пикселей для каждого пространства. 30 | 31 | Дополнительная информация: 32 | 33 | - Для поиска пространств можно использовать DFS; 34 | - Для пикселя смежными пикселями считаются 4 пикселя с которыми он имеет общую грань. Исключением являются пиксели, которые находятся по краям поля; 35 | - Для пространства смежными пикселями считаются все те пиксели, которые являются смежными для любого из пикселей пространства. Множество смежных с пространством пикселей можно визуально представить как границы этого пространства. 36 | 37 | ## Этап 3. Мутация 38 | 39 | 1. Реализовать алгоритм мутации. Каждый шаг мутации заключается в том, что каждое пространство выбирает случайный смежный пиксель и красит его в свой цвет; 40 | 2. Реализовать перегенерацию и перерисовку поля после каждого шага мутации; 41 | 3. Потестировать на квадрате 30х30, осознать проблемность перерисовки и реализовать инкрементальную перерисовку поля. 42 | 43 | - Для того, чтобы наблюдать за изменениями, проще всего написать в Program.Main `while(true)` и добавить в него `Console.ReadKey()`. Тогда можно тыкать пробел и смотреть, как происходит одна итерация. Когда станет ясно, что всё хорошо, можно заменить ReadKey на `Thread.Sleep(400)` (это приостановит выполнение программы на 400 миллисекунд); 44 | - Инкрементальная прорисовка подразумевает, что нужно сохранить поле, которое было прорисовано на прошлом этапе. Не стоит пытаться доставать текущий цвет консоли, лучше научиться клонировать данные поля. 45 | 46 | ## Этап 4. Дополнительные задачи 47 | 48 | - Реализовать возможность задавать скейл пикселей. Например, задаём поле 10х10 и скейлинг х2. В итоге логических пикселей будет 100, но рисовать на консоль нужно поле 20х20, каждый пиксель будет занимать 2х2 символов консоли; 49 | - Добавить вероятность мутации. Пространство может мутировать с какой-то вероятностью, которая зависит от его размера. В зависимости от того, как именно задаются эти правила, поле красится очень разными стратегиями. 50 | 51 | ## Пример результата 52 | 53 | ![colonizer-demo](./Colonizer-demo.gif) 54 | -------------------------------------------------------------------------------- /Archive/Onboarding-way.md: -------------------------------------------------------------------------------- 1 | # Onboarding way 2 | 3 | Onboarding task - это цепочка из задач, которые предлагаются новым участникам Kysect для того, чтобы они лучше ознакомились с инструментами, библиотеками и подходами, используемыми при написании приложений. В каждом этапе будет описан ряд задач, которые нужно выполнять итеративно - для каждой задачи создавать ветку, реализовывать решение и закидывать PR на ревью. 4 | 5 | ## Тематика задачи 6 | 7 | Цель проекта - разработать клиент-серверное консольное приложение для игры в лабиринт. В рамках реализации будет создан сервер - консольное приложение, которое генерирует лабиринт и предоставляет возможность клиентам подключаться к нему и передвигаться. Клиент - это ещё одно консольное приложение, которое подключается к серверу, получает лабиринт и даёт возможность управлять объектом, который находится в лабиринте. 8 | 9 | Игра будет происходить на прямоугольном поле, по которому могут перемещаться объекты. Ввиду того, что приложение будет консольным, перемещаться они будут по консольным ячейкам в 4 стороны. Управление должно быть реализовано посредством нажатия клавиш WASD. Помимо объектов в лабиринте будут существовать стены, через которые объекты не могут перемещаться. 10 | 11 | ## Этап 1. Генерация лабиринта 12 | 13 | Для игры нужно генерировать лабиринт определённым образом: 14 | 15 | - Любая его точка должна быть достижима из другой точки 16 | - У него должен быть один выход 17 | 18 | Задачи на первый этап: 19 | 20 | - Сгенерировать лабиринт, используя библиотеку MazeGenerator и реализовать отрисовку в консоли; 21 | - Реализовать генерацию объекта в лабиринте с возможность задавать минимальное расстояние к выходу (для того, чтобы объект не генерировался близко к нему). 22 | 23 | ## Этап 2. Оживление объекта 24 | 25 | Во втором этапе нужно оживить объект, чтобы им можно было передвигаться по лабиринту 26 | 27 | - Реализовать передвижение сгенерированного объекта через WASD; 28 | - Реализовать возможность ограничивать видимость объекта и отображать только лабиринт в радиусе N ячеек вокруг объекта, которая не скрыта стенами; 29 | - Реализовать отрисовку таким образом, чтобы объект находился в центре консоли; 30 | 31 | Пример правильного отображения: 32 | 33 | Если лабиринт выглядит так: 34 | ``` 35 | XXXXX 36 | Xo X 37 | XX X 38 | X X 39 | X X 40 | XXXXX 41 | ``` 42 | 43 | То после ограничения видимости до двух шагов, лабиринт должен быть отображаться так: 44 | ``` 45 | ~~~~~~ 46 | ~XXXX~ 47 | ~Xo ~ 48 | ~XX ~ 49 | ~~~~~~ 50 | ``` 51 | 52 | ## Этап 3. Создание игрового контекста 53 | 54 | На этом этапе требуется реализовать игровой контекст. Игровой контекст - это лабиринт и игроки, которые в нём находятся. 55 | 56 | - Добавить возможность сохранять. При запуске приложения пользователь может ввести название игры. После каждого шага пользователя игра должна автоматически сохраняться; 57 | - Добавить возможность загружать лабиринт. При запуске приложения пользователь может ввести название игры. Если у игры с таким названием уже есть, то загружать её; 58 | - Добавить возможность при запуске указать не только имя игры, но и имя пользователя. Если такого пользователя нет, то создать для него объект. Если есть, то загрузить его локацию. 59 | 60 | Для сохранения можно использовать: 61 | 62 | - JSON 63 | - Базу данных 64 | 65 | ## Этап 4. Клиент-серверное решение 66 | 67 | На этом этапе предлагается разделить серверную и клиентскую часть на два отдельных процесса, чтобы была возможность нескольким игрокам сразу перемещаться по лабиринту. 68 | 69 | - Разделить решение на два проекта - серверная часть и клиентская. Серверная часть должна предоставлять набор интерфейсов, которые клиентская часть может вызывать для управления; 70 | - Реализовать возможность клиенту подключаться к серверу по TCP и присоединяться к игре или создавать её; 71 | - Реализовать возможность клиенту подключаться к серверу по TCP и перемещаться по лабиринту. 72 | 73 | ## Этап 5. Добавление игровых механик 74 | 75 | 5-ый этап будет добавлен позже. 76 | -------------------------------------------------------------------------------- /Learn/Articles/Do-less-do-more/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Do-less-do-more/img/img-1.jpg -------------------------------------------------------------------------------- /Learn/Articles/Do-less-do-more/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Do-less-do-more/img/img-2.jpg -------------------------------------------------------------------------------- /Learn/Articles/Do-less-do-more/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Do-less-do-more/img/img-3.jpg -------------------------------------------------------------------------------- /Learn/Articles/Do-less-do-more/readme.md: -------------------------------------------------------------------------------- 1 | # Делай меньше, делай больше 2 | 3 | Когда я год назад смотрел на своего лида - у меня постоянно появлялся вопрос: "А почему он не делает вот так?". Это касалось разных вещей, в том числе ведения некого current state'а по текущим задачам _регулярно_. Я охотно каждый день его обновлял и удивлялся почему так не делаю другие. Но шло время, сначала количество задач на мне стали превышать мою скорость их закрытия, обновлять стейт по каждой было все сложнее. А если смотреть на сегодняшний день - их количество увеличилось где-то в 8 раз. Стало понятно, что тайм менеджмент либо спасёт, либо погубит. 4 | 5 | Постараюсь рассказать как не умереть от таких изменений в жизни (или хотя бы протянуть чуть больше), при этом не доводя это все до советов "Спи эффективнее!". И перед тем как пытаться оптимизировать что-то, стоит задать себе вопрос: "А зачем это делать?". С жизнью все просто: быстрее сделал лабы - больше времени на себя. С работой чуть менее очевидно. Казалось бы - нужно отработать 8 часов, что изменится от того, что я чуть более эффективно поработаю если все равно потом возьму следующую задачу? Ответ на этот вопрос есть смысл задать еще раз, ближе к концу. 6 | 7 | Небольшой план, чтобы можно было перепрыгнуть к интересующему: 8 | 9 | 1. TODO 10 | 2. Код (на примере C#) 11 | 3. Teamwork 12 | 13 | ## Todo 14 | 15 | А для начала решим что же делать, если время уже закончилось, хотя работаю я все еще на 120%. Во-первых, начать осознавать ситуацию, объем проблемы. В этом помогает TODO-лист. Это довольно стандартный совет, но нужно понимать зачем этом лист нужен, вы же тратите время на его ведение - значит ожидаете что-то получить? Туду решает две проблемы: память и метрики. Я, как человек с напрочь отбитой памятью, не могу в себе хранить задачи на более чем день - постоянно что-то забывается, а потом вспоминаю через 4 месяца что хотел человеку написать. Но важнее тут именно метрики. Количество задач - неплохой показатель загруженности. Если вы замечаете, что на сегодня у вас две задачи висит, а на завтра шесть - можно задуматься о том, что будет неприятно, если какую-то задачу не попробовать решить сегодня. Также это поможет ответить на вопрос "А ты как, не занят?". Задачи могут быть по объему довольно разные, научить и приучить себя их декомпозировать - это тоже неплохой шаг к более эффективному учету задач. Но нужно не перестараться - записывая все свои хотелки есть вероятность наспамить кучу задач, которые не будут выполнены (вообще или хотя бы в течении полугода). Они будут путать вас с оценкой загруженности и демотевировать - такое лучше скидывать в отдельную помойку "Если бы в сутках было 30 часов". 16 | 17 | ![](img/img-1.jpg) 18 | 19 | Ещё одна причина вести учет своих задач - синхронизация с другими людьми. Задачи иногда подразумевают коммуникацию, кооп или зависимость других людей/задач. В такой ситуации неизбежны "Ну как там? Когда готово будет? А что уже сделал? А ты можешь посмотреть это завтра?". Большая часть таких вопросов сразу отпадут, если у человека есть доступ к вашему списку задач. Один убранный такой вопрос - экономия времени двух человек. Я, к примеру, не представляю сколько бы лишнего времени я постоянно убивал, если бы не имел возможности отслеживать активность своих тимейтов которым я делегирую задачи. Поэтому, при работе в команде, даже если людей мало а "проект" на десяток задач максимум - договоритесь о способе контроля задач. Как бонус, вы получите лишний повод документировать свои действия и расписывать подробности реализации. Разумеется, есть черта после которой учет превращается в необоснованную трату времени, с этим тоже нужно быть осторожным. 20 | 21 | На скриншоте - Mircosoft To Do, очень удобный инструмент для задач с синхронизацией и с мобильными клиентами. 22 | 23 | ## Код 24 | 25 | Дисклеймер: содержит много рекламы языка C# и инструментов для работы с ним. 26 | 27 | Туду вещь всё же вариативная, абстрактная, попробуем посмотреть на более приближенные примеры - как код писать и как его читать. Начнем со второго. Сразу проговорю банальную фразу - "код редко пишут и часто читают". Возможно, это не так очевидно, когда дело касается университетских лабораторных, которые сделались за ночь. Но как только руки доходят до больших проектов - становится понятно, что большую часть времени будет занимать чтение и это нормально. Во время такого перехода ранее тривиальные задачи обретают совершенно иной объем сложностей. Казалось бы, что мешает взять и пройтись по папкам, чтобы найти где лежит какой-то класс? Наверное то, что в проекте файлов резко стало несколько сотен, папки исчисляются десятками, а желание смотреть после 6-ого файла уже нет. Именно в такой ситуации нужно вспомнить про инструменты для разработки. Если конкретно про описанный случай, то решения будут сводиться к поисковым тулзам. Для C#'а есть прекрасная вещь Resharper, хотя и сама Visual Studio умеет делать приятно. Три фичи без которых я бы не смог читать код: 28 | 29 | Поиск текста. Решарпер умеет делать как полнотекстовый поиск по всей кодовой базе, так и "умный поиск" по названиям классов. 30 | Поиск использований и value origin. Это функционал который я хотел сделать руками, когда впервые попал на большой проект (тогда еще не знал, что решарпер умеет это делать так хорошо) - построение дерева вызовов метода. Т.е. тыкнув один хоткей на метода можно сразу посмотреть все места где метод вообще используется, а не ходить и искать. Как бонус - древовидность, можно посмотреть где используется метод, который использует интересующий метод, и так дойти до самого старта программы. 31 | Построение дерева наследования и реализаций. Т.е. для типа (или его метода) можно в один хоткей посмотреть наследников (или реализацию в случае метода). 32 | Важным аспектом также является нейминг. Я встречал людей, которые горели на придирки к названиям и это вызывало у меня вопросы. Давая название классу вы можете как объяснить читателю причину существования класса и название, так и ввести в заблуждение и создать ложное чувство понимания происходящего. Это одна из причин почему следует таки уделить внимания изучению паттернов (понимать что значат слова "Билдер" и "Адаптер") и всяким абстрактным вещам как Domain Design (научиться разделять логику на сущности так, чтобы их понимали другие). Немного апнув свои навыки чтения можно хорошо так сэкономить время на его чтение - понимать суть классов не рассматривая его детали. 33 | 34 | Но что же про написание кода? Тут все просто: эффективность можно измерить объемом кода, который за вас пишут ваши инструменты. Мой любимый пример - это работа с enum'ами. Имея код 35 | 36 | ![](img/img-2.jpg) 37 | 38 | Можно одним движением сгенерировать подготовленный оператор switch, который будет содержать все параметры enum'а: 39 | 40 | ![](img/img-3.jpg) 41 | 42 | И это просто спасение. Каждый раз, когда вы делаете какое-то шаблонное действие, стоит задуматься "а могут ли инструменты сделать это за меня?". Ведь таких микромоментов очень много и они все выстраиваются в одну большую оптимизацию. Набросаю небольшой список того, что советую попробовать открыв C#-проект (можете прямо сейчас в своем todo-листе завести задач!): 43 | 44 | Ренейм. Решарпер умеет это делать очень хорошо! Он предложит переименовать связанные классы, если они содержат подстроку, или переменные этого типа, если у нее совпадает имя хоть ка-кто 45 | Автоимплементация интерфейсов. Если класс должен реализовать интерфейс, то ваш код прекрасно знает какие методы должны там быть и может сам сгенерировать их сигнатуру 46 | Инверсия условий. Я думаю не мне одному приходилось иногда менять местами текст в if и else по разным причинам. Это довольно простое действие, которое за вас тоже могут сделать инструменты! 47 | Кажется, метод стал слишком большим? Не беда, решарпер может за вам вынести его кусок в другой метод! (или наоборот заинлайнить) 48 | Перемещение порядка аргументов в метода, удаление не используемых в вызывающем код - это все тоже не стоит делать руками. 49 | ctor, ctorp, prop - это мастхев шаблоны, которые пишут код. 50 | А если вы познали дзен - нельзя останавливаться! Ведь есть много расширений, освоив которые можно писать код быстрее, приятнее и не отвлекаясь на ерунду: 51 | 52 | Если автокомплита не хватет - есть лайфтемплейты, например ZenSharp. Это расширение для решарпера, которое превратит объявление любого поля класса в написание 3-4 символов (https://github.com/ulex/ZenSharp) 53 | Если вам повезло меньше и вы не пишете на C# - для вас все равно найдется что-то полезное! Например, если у вас постоянно дергается глаз от упоротых SQL-скриптов, а писать как-то нужно - есть форматеры, которые за вас будут проблемы отступов и всего такого (https://www.apexsql.com/sql-tools-refactor.aspx) 54 | Но работа с кодом не ограничивается написанием его. Приходится работать с системами контроля версий, которые тоже отнимают время. Например, наслушавшись других разработчиков можно поставить себе консоль и пытаться через нее работать с гитхабом убивая весь UX и усложняя даже простые вещи. Да, люди, которые много лет работали так - привыкли, даже могу поверить, что у них первоманс больше, но если за плечами нет такого опыта, а работа с гитом может еще вызывать трудности - перекладывайте их на GUI для GIT'а. Например, GitKraken. За довольно короткое время использования можно найти те пару кнопок, которые нужно наживать и все уже будет казаться более прозрачным. Написание команд будет сводиться к тыканию на нужные кнопки, а просмотр истории - на скролинг в GUI. Например, с помощью GitKaraken можно создать репозитория сразу на гитхабе, закомитить и запушить туда свои изменения. Или удобно создать и отправить пул-реквест в чей-то репозиторий - это все находится в одном месте и имеет интуитивный интерфейс. 55 | 56 | Не забывайте про существования библиотек. Помните, что скорее всего вашу задачу (или ее подтаску) уже кто-то пытался решить. Если вы задумываетесь о написании собственного парсера HTML - остановитесь, подумайте еще раз хотите ли вы этого или же вам достаточно просто взять готовую библиотеку и написать 10 строчек для решения проблемы? 57 | 58 | ## Тимворк 59 | 60 | Работа в команде - это всегда издержки. Работая, один человек не тратит время на синхронизацию или объяснения своих задач/результатов. Но с другой стороны - один человек всегда ограничен временем, которое у него есть на проект. И в какой-то момент становится понятно, что издержки оправданы. Вопрос в том, насколько много придется за это платить. Отличный тому пример - вопросы. Есть две крайности этой проблемы. С одной стороны, есть люди, у которых есть цель - узнать ответ на свой вопрос и остальное их не сильно касается. Такое можно наблюдать в больших телеграм чатах о ЯП - "У меня не работает код, что делать?". Такой вопрос не несет много информации и читателю нужно будет потратить достаточно много времени, чтобы вникнуть. А потом еще может оказаться, что ответ - это первая ссылка в гугле. Схожая ситуация - это вопросы "А кто-то работал с _технология-нейм_?". Эта ситуация хорошо описана тут: https://nometa.xyz/. Другая крайность - это типичные джуны, которые сидят с проблемой и боятся ее задать т.к. наоборот ставят время других людей свыше своей проблемы. Стоит отдавать отчет, что проблема таким образом не решается, а в какой-то момент ее все равно нужно будет переложить на плечи более опытного коллеги. 61 | 62 | Еще один кейс - это ситуации, когда нужно наоборот информацию донести. Рассказать кому-то о своих успехах/проекте. И в зависимости от обстоятельств и размера аудитории до которой нужно донести, есть ряд решений. Поделиться с другом своей идеей - наверное, проще созвоном в дискорде. Обсудить план действий группе людей - возможно, стоит составить текстовый док и зашарить. Хочется донести свои знания и свой проект в массы? Выберите оптимальные способы, возможно даже раскошельтесь и потратьте время на составление диаграмм (о шок, оказывается людям картинки смотреть проще чем читать!). Не правильно выбрав стратегию однажды я обрек себя на пересказ шаблонной информации десятку людей. Хотел сэкономить, ведь так лень писать полобные лонгриды - убил еще больше времени. Но и не стоит забывать о времени собеседника. Выплеснув кучу воды, забивая поток информации чем-то слабосвязанным с темой можно потратить кучу его времени (а потом он сделает также по отношению к вам!). 63 | 64 | Подводя итог - думайте о том, как поймет вас ваш собеседник, что ему нужно будет сделать чтобы ответить на ваш вопрос. Стоит ли потратить еще какое-то время на подготовку дополнительно информации по проблеме или он и так все знает и быстрее ответит чем вы что-то сделаете. 65 | 66 | Если вы вдохновитесь и захотите порисовать - советую посмотреть на StarUML, удобная программа для построения графиков. А если нужно организовать задачи между командой - посмотрите в сторону To do который умеет шарить списки задач между аккаунтами или GitKraken Glo - доска (как трелло, да) для менеджмента задач которая встроенная в GitKraken и имеет очень неплохую интеграцию. 67 | 68 | ## Итог 69 | 70 | Я постарался скипнуть все темы связанные с прокрастинацией и прочим. Нужно понимать, что невозможно работать 100% времени. Часть времени все равно будет уходить на общение с коллегами, просмотр мемов про дженерики в Го или холиваром "нужно ли использовать LINQ". Но даже без этого - минимизировав время на написание бойлер кода, на повторное объяснение тестировщику что ты сделал вчера (потому что не написал доку), или попытки вспомнить чем занимался вчера чтобы ответить лиду - в рабочем графике можно выкроить дополнительно время на более интеллектуальные задачи, которые помогут развиваться. Или получить дозу позитивных эмоций за счет похвалы от лида за своевременность выполнения. 71 | 72 | Делай меньше рутины, чтобы успевать делать больше импакта! И не забывайте, что время - это тоже ресурс, который нужно уметь пользоваться. -------------------------------------------------------------------------------- /Learn/Articles/How-to-dispose.md: -------------------------------------------------------------------------------- 1 | # How to: dispose 2 | 3 | Тут и далее будем под ресурсами (для упрощения) называть экземпляры IDisposable, а под очисткой - вызов метода Dispose. 4 | Частая проблема управления ресурсами состоит в том, что не очевидно, кто должен ресурсы освобождать. Например, когда мы создаём объект, который реализует IDisposable, то оборачиваем его в using – всё просто. Но что, если мы передаём такой экземпляр внутрь какого-то метода? Можем ли мы гарантировать, что внутри метода не будет закеширован этот объект, который впоследствии будет задиспоужен, но при этом сохранён где-то в кеше, что означает вероятность обращения к нему – уже задиспоуженному объекту? Или если такой объект будет задиспоужен в методе, то получится так, что мы дважды будем его диспоузить (внутри метода и через использование конструкции using)! Рассмотрим самые частые ситуации и вопросы. 5 | 6 | Кто должен освобождать ресурсы? Однозначно ответить сложно. Усложняет ситуацию то, что наш код может использовать другие решения, которые имеют свои представления о работе с ресурсами. Но в ситуации, когда всем кодом можно управлять, применяют подход, когда ресурсы освобождает тот, кто их получил. Очень способствует этому синтаксис using, он форсит нас к тому, чтобы сразу объявить и создание, и освобождение. 7 | 8 | А если ресурс передаётся аргументом, то что с ним делать? Его можно использовать, но его не стоит диспоузить, т.к. вызывающему коду будет не очевидно, почему его объект уже не может быть использован. Если при этом ресурс необходимо сохранить внутри класса, который получает ресурс, то такой класс должен транзитивно становиться IDisposable. Это значит, что любой класс, который содержит в качестве полей IDisposable, должен диспоузится. 9 | 10 | Значит, если я не буду вызывать .Dispose на ресурсе, который прокидывается аргументом, то никаких проблем не возникнет? До тех пор, пока не будет вызвано освобождение неявно. Одна из таких ловушек описана чуть выше в качестве совета. Если мы создадим класс, передадим ему ресурс, а потом его задиспоузим, то ему очень захочется задиспоузить его. Есть ли уверенность, что `using (var reader = new StreamReader(stream))` не будет вызывать stream.Dispose? 11 | 12 | А что делать с тем, что Dispose вызывается дважды? Краткий ответ - ничего, страдать. Решить проблему довольно сложно, т.к. всё завязывается на детали реализации кода другими разработчиками. Единственный хороший момент – это рекомендации Майкрософта по имплементации паттерна Disposable. В них указано, что метод Dispose нужно реализовывать так, чтобы повторный вызов ничего не ломал. Из грустных моментов – это работает не всегда: даже стандартные TcpClient бросают ошибки при повторном вызове Dispose. 13 | 14 | Нужно ещё отметить очень очевидный момент. Dispose – это метод экземпляра и вызывается на нём. Из этого следует очень неприятный вывод: "нельзя вызвать Dispose, если нет объекта". Представим ситуацию, что в конструкторе создаётся два экземпляра класса Stream и сохраняются в поля. Разумеется, что мы помним про то, что их нужно освобождать и в методе Dispose будем это делать. А теперь представим, что мы создали первый экземпляр, а на создании второго упали с ошибкой. Вызывается ли освобождение созданного экземпляра? Нет. Мы упали в конструкторе, не успели создать экземпляр, а значит не можем вызывать метод Dispose. В этой ситуации using не сильно то поможет и нужно контролировать выполнение с помощью try-catch и соответствующе обработать такую ситуацию. -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-1.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-10.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-11.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-2.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-3.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-4.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-5.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-6.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-7.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-8.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/img/img-9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Jinder/img/img-9.jpg -------------------------------------------------------------------------------- /Learn/Articles/Jinder/readme.md: -------------------------------------------------------------------------------- 1 | # А что писать? 2 | 3 | ## Предисловие 4 | 5 | Практически у каждого, кто начинает изучать язык программирования, рано или поздно возникает вопрос: а что, собственно, делать со знаниями этого языка? Самый простой и наиболее популярный ответ – применить на практике свои знания и написать пет проект. 6 | 7 | Мне понадобилось более семи месяцев, чтобы наконец ответить себе на этот вопрос и начать писать что-то больше лабораторной работы или скрипта из десяти строк. Случилось это всё благодаря попаданию в Veeam Academy, где личный проект – обязательная часть курса, и хочешь не хочешь, но придётся его писать. 8 | 9 | Дальнейшей историей успеха разработки я постараюсь выделить основные этапы создания своего проекта и обратить внимание на главные ошибки и способы их избежать. 10 | 11 | ## Идея 12 | 13 | Для начала нужно определиться с концепцией того, что будет разрабатываться. Здесь мы и встречаемся с первой и довольно большой ошибкой: в голову приходит гениальная идея написать что-то необходимое всему миру, что уничтожит бедность, рак и обеспечит мир во всем мире. Но чудо не произойдёт, и скорее всего ваш первый проект - то, что просто поможет вам закрепить знания на практике, и хорошо бы, чтобы это было приложение, которое необходимо именно вам. Это поможет сохранить интерес к разработке и позволит дорабатывать ваше приложение ещё долгое время. 14 | 15 | Я же пошел по другой дороге и решил, что круто бы было заняться проблемой поиска работы и написать приложение, которое облегчит контакт работодателей и специалистов (да, hh 2.0), а ещё и оформить это в стиле Тиндера. Грандиозная идея, и вроде бы даже есть, что писать, но по окончании академии моя дальнейшая разработка приложения ограничилась лишь парочкой правок и отправлением проекта в архив. Вот так и зародился Jinder (Job + Tinder). 16 | 17 | Итого, урок номер один - занимайтесь догфудингом. Найдите то, что вам нужно в повседневной жизни: агрегатор скидок в стиме, фильмов на кинопоиске, бот для работы с ИСУ. 18 | 19 | ## Проектирование 20 | 21 | Неожиданно, но иметь только идею не достаточно, нельзя просто сесть и начать писать код (вообще можно, но надолго ли вас хватит без чёткой задачи и понимания того, что нужно делать?). Для начала полезно выделить основной функционал приложения – собственно, те возможности, которые мы хотели бы получить в итоге. 22 | 23 | В моём случае вышел небольшой список жизненно важных функций приложения: 24 | 25 | * Авторизация пользователей 26 | * Создание профиля вакансси/резюме 27 | * Подбор кандидатов согласно вакансии(и наоборот) 28 | * Механизм оценки вакансии/резюме 29 | * отказ: навсегда скрыть предложение из подборки 30 | * отложить: временно убирает предложение с последующим возвращением в подборку 31 | * одобрение: взаимное одобрение вызовет "матч" 32 | * Матчинг и обмен контактами 33 | Помимо этого был ещё список второстепенных фичей, но упоминать его не будем, так как до их реализации я так и не добрался. 34 | 35 | Базовый функционал выделен, пришло время воплощать в жизнь желаемое, но не так быстро. Накидать всё "лишь бы как" можно, но хочется же сделать всё гибко и адаптивно, чтобы легко было найти багу или допилить новую фичу. Первостепенно стоит разделить своё приложение на слои. Так как задачей личного проекта было создать клиент-серверное приложение, очевидно, что можно (и даже нужно) отделить всю логику приложения от пользовательского интерфейса. Пользователей, их резюме и вакансии нужно где-то хранить, значит выделим ещё и слой работы с базой. Итого классическое трио из слоёв приложения: 36 | 37 | * UI (user interface) 38 | * BLL (business logic layer) 39 | * DAL (data access layer) 40 | Слои есть, теперь стоит углубиться в слой бизнес логики и понять, с чем нам предстоит работать. Необходимо выделить модели и продумать их взаимодействие. Наиболее удобно делать это всё визуализируя, тут на помощь приходит UML и крутые профессиональные редакторы для него. Но за неимением опыта и знаний я прибегнул к работе с app.diagrams.net. Это очень простой и не менее функциональный редактор диаграмм, где имея базовые представления о UML (я прочёл 1.5 статьи из гугла) и ООП можно визуализировать свои модели. Вышло как-то так: 41 | 42 | ![](img/img-1.jpg) 43 | 44 | ## Разработка 45 | 46 | Наконец-то можно писать код! Или всё ещё не писать... Вспомним, что у нас клиент-серверное приложение, а значит клиент с сервером должны взаимодействовать посредством запросов. Тут есть выбор из сложного и довольно старого WCF и более современного ASP.NET Web API. Я выбрал ASP.NET, так как у меня уже был некий опыт работы с ним. 47 | 48 | ### Самая большая ошибка 49 | 50 | Уже на этом моменте стоит выделить главную ошибку начинающих разработчиков – стремление сделать всё идеально с самого начала. Вместо часов обдумывания, как всё сделать максимально хорошо, можно сделать рабочий прототип и впоследствии отрефакторить, доработать и получить тот самый "идеал". 51 | 52 | ### API 53 | 54 | В ASP Api строится из контроллеров. Контроллеры должны обрабатывать запросы и обращаться к логике нашего приложения, а значит никакой логики в контроллерах нет, но если не там, то где? Тут на помощь приходит чудо-недопаттерн Controller-Service-Repository. 55 | 56 | ![](img/img-2.jpg) 57 | 58 | Всю логику мы разбиваем на единицы, называемые сервисами: с ними взаимодействуют контроллеры, а вся работа с базой инкапсулирована в репозитории. Просто, элегантно, эффективно. 59 | 60 | Вернёмся к контроллерам. При получении запроса сервер должен уметь идентифицировать пользователя. Делать это будем посредством токенов передаваемых вместе с запросами. А чтобы каждый контроллер умел понимать, что за пользователь прислал запрос, я определил базовый контроллер аутентификации, от которого будут унаследованы все другие контроллеры. 61 | 62 | ![](img/img-3.jpg) 63 | 64 | Теперь в любом контролере, унаследованном от этого, мы будем иметь доступ к методу ValidateToken, который по токену вернёт нам Id пользователя. 65 | 66 | Когда-то позже я узнаю, что это не нужно было делать руками, ведь в ASP из коробки работает авторизация, и сделать всё это можно было парочкой атрибутов. 67 | 68 | Пример метода UserController получения информации о пользователе, который отправил запрос. 69 | 70 | ![](img/img-4.jpg) 71 | 72 | Для незнакомых с контролерами ASP разработчиков выглядит страшно и непонятно, но самое главное, что можно выделить отсюда: 73 | 74 | * метод вызывается посредством http get запросов 75 | * возвращает один из 3 статус кодов, для этого мы оборачиваем возвращаемое значение в ActionResult 76 | * для получения объекта пользователь мы обращаемся к сервису UserService 77 | 78 | ### Dependency Injection 79 | 80 | Уже может возникнуть закономерный вопрос: как нам связать контролеры и сервисы, а впоследствии сервисы и репозитории? Всё верно: будем в конструктор контроллера передавать сервисы, аналогично с сервисами – будем передавать в них репозитории. А чтобы потом с этим было просто работать, воспользуемся Dependency Injection и встроенным в ASP DI контейнером. DI – мощная, полезная и простая технология, с которой безусловно стоит ознакомится. 81 | 82 | По итогу Startup нашего ASP приложения наполнится подобными строками: 83 | 84 | ![](img/img-5.jpg) 85 | 86 | Теперь контейнер сам будет подставлять в конструкторы реализации интерфейсов. 87 | 88 | ### Тестирование 89 | 90 | Как только начинаешь писать логику, уже хочется быть уверенным, что всё работает, как задумано. Здесь на помощь приходит unit-тестирование. Для него я завёл отдельную сборку для тестов и воспользовался фреймворком для создания тестов NUnit. 91 | 92 | NUnit - чудесная возможность погрузится в мир максимально читаемых ассертов с помощью класса Is: 93 | 94 | ![](img/img-6.jpg) 95 | 96 | Как же нам тестировать сервисы в отрыве от репозиториев? Добро пожаловать в мир моков и библиотеки Moq. Достаточно подсунуть в конструктор вместо объекта: 97 | 98 | ![](img/img-7.jpg) 99 | 100 | Вуаля, и у нас есть реализация интерфейса, которая при вызове Get(0) всегда возвращает нужное нам значение. 101 | 102 | ### Работа с БД 103 | 104 | Первоначально вместо обращений в базу я сделал замоканные реализации репозиториев, в которых данные хранились внутри коллекций. Чтобы работать с реальной базой, я решил использовать Entity Framework. Если вам не критично важна скорость обращений в базу, то это идеальный выбор. Entity Framework – ORM от Microsoft, которая позволяет, описав в коде модели базы данных, легко и просто взаимодействовать с базой. 105 | 106 | Моя работа началась со слов: "Сделаю пару табличек за вечер и база готова", а закончилась несколькими днями усердных разборок с EF, связями, миграциями и вопросами "А почему?". Благо на всё можно найти ответы на MSDN, и по итогу я получил такую базу: 107 | 108 | ![](img/img-8.jpg) 109 | 110 | А обращения в базу выглядели кратко и красиво (по-моему субъективному мнению): 111 | 112 | ![](img/img-9.jpg) 113 | 114 | ### UI 115 | 116 | В разработке пользовательского интерфейса приложения важно помнить, что первостепенную важность имеет функциональность этого интерфейса, а не его внешний вид. Я пренебрёг этим советом и убил кучу времени на красивую менюшку. В итоге у меня красивое меню и UI, в котором часть готовых на сервере фичей попросту не реализованы. 117 | 118 | ![](img/img-10.jpg) 119 | 120 | Весь UI сделан на WPF. Столько болей и мучений я давно не испытывал, зато познакомился с контролами, биндингами, командами и прочими прелестями WPF. А эта чудо менюшка создана с помощью ModernWPF. 121 | 122 | А раз мы затронули пользовательский интерфейс, то стоит уделить внимание и тому, как соединить готовые фичи бэкенда с UI. На стороне сервера уже готова Web API, взаимодействовать с которой можно посредством http-запросов. Но прописывать запрос для каждого обращения к серверу это слишком долго, поэтому я воспользовался Refit. 123 | 124 | Refit - чудесный инструмент, который позволяет все взаимодействия с сервером свести к описанию интерфейсов подобного вида: 125 | 126 | ![](img/img-11.jpg) 127 | 128 | Теперь мы можем получить экземпляр класса с помощью RestService.For(Session.HostUrl) . При вызове нужных нам методов будут автоматически отправляться запросы на сервер, а полученные запросы будут десериализованы. 129 | 130 | ## Итог 131 | 132 | Я не получил идеального продукта и даже приложения, которое теперь использую, но я получил самое главное - опыт. Огромный опыт разработки приложений, опыт работы с большим количеством технологий. Помимо этого я встретился с множеством проблем и большинство даже решил. 133 | 134 | Это был мой первый опыт проектирования, и почти всё я сейчас сделал бы по-другому, но понимание этого пришло только благодаря практике. Отсюда и главный совет – пробуйте, практикуйтесь. Начиная с чего-то малого и довольно простого, вы тоже получаете навыки, которые пригодятся в последующей разработке. Не бойтесь работать с новыми для вас технологиями, разработчики уже придумали бесконечное множество полезных и эффективных инструментов для большинства ваших задач. 135 | 136 | ## Ссылки 137 | 138 | - Jinder (https://github.com/s4xack/Jinder) 139 | - Цикл статей о создании WEB Api проекта на ASP (https://www.forevolve.com/en/articles/2017/08/11/design-patterns-web-api-service-and-repository-part-1/) 140 | - Dependency Injection (https://docs.microsoft.com/ru-ru/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1) 141 | - Unit тестирование (https://metanit.com/sharp/aspnet5/22.1.php) 142 | - Moq (https://github.com/Moq/moq4/wiki/Quickstart) 143 | - Refit (https://github.com/reactiveui/refit) 144 | - ModernWPF (https://github.com/Kinnara/ModernWpf) -------------------------------------------------------------------------------- /Learn/Articles/Make-types-not-classes/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Make-types-not-classes/img/img-1.jpg -------------------------------------------------------------------------------- /Learn/Articles/Make-types-not-classes/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Make-types-not-classes/img/img-2.jpg -------------------------------------------------------------------------------- /Learn/Articles/Make-types-not-classes/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Make-types-not-classes/img/img-3.jpg -------------------------------------------------------------------------------- /Learn/Articles/Make-types-not-classes/make-types-not-classes.md: -------------------------------------------------------------------------------- 1 | Если вы уже ознакомились с ООП, то знаете общие подходы. Но так уж сложилось, что они у большинства разработчиков ООП связано с наследованием, полиморфизмом, инкапсуляцией. Другими словами - с правилами как использовать разработанный концепт. Но абсолютно никто не говорит о том, как это правильно описывать, как выделять те классы, которые потом будут наследоваться. На такие вопросы можно найти ответы в этой книге. Если попытаться ее описать кратко - она про то, как научиться правильно описывать то с чем вы работаете на формальном языке. 2 | 3 | 4 | Человека далекого от программирования и человека, который начал хоть немного что-то изучать, разделяет умение вбивать код с IDE. Именно вбивать, неплохая формулировка, как мне кажется. Я открываю новый язык, начинаю гуглить как сделать что-то, копирую, запускаю. Это все откладывается и через какое-то время наступает новый этап - осознанное написание кода. 5 | Но есть небольшая проблема - мы все еще "вбиваем" код. МЫ продолжаем формулировать себе задачи в стиле "Написать код, который...". И вот тут появляются проблемы. 6 | 7 | ## MemorySize 8 | 9 | Чтобы понять проблемы, рассмотрим довольно простую задачу: нужно описать логику работы с размером файлов в коде. Какие есть возможные решения? Скорее всего, вы не задумываясь уже были готовы написать int fileSize и хранить размер в байтах. Если задумались - то написали бы Int64 fileSize. Почему так? Очевидно, потому что размер - это целочисленное значение, а в Int32/Int64 к тому же определены все операторы (+ и -). Но давайте попытаемся решить первую проблему: взаимодействие с UI. Пользователи будут взаимодействовать с вашим продуктом именно через него, и если у вас имеется функционал ввода размеров файлов и вы не хотите, чтобы пользователи возненавидели вас - в UI появится возможность работать с мегабайтами или гигабайтами. В части вашего UI появится новый int fileSize, который уже хранит мегабайты. И все бы хорошо, ведь мы можем умножить на 1024^2 и получить размер в байтах. Можем, но не забудем ли? Можно бесконечно долго убеждать себя в том, что разработчики не будут ошибаться, надеяться, что они будут держать все нюансы в голове, но если в вашем проекте есть хотя бы один коммит с префиксом "fix:" - кажется, ошибиться таки можно. Как только вы реализуете в какой-то части продукта логику работы с размером - вы о ней забудете. Когда вам следующий раз нужно будет с этим работать - есть вероятность, что вы просто увидите в IntelliSense "fileSize" и скажите себе "О, то что нужно, currentSize + fileSize". В лучшем случае - вы просто потратите какое-то время на то, чтобы найти где этот размер выставляется, чтобы понять размерность. 10 | 11 | ![](img/img-1.jpg) 12 | 13 | ## Решим проблему (очень просто) 14 | 15 | И так, мы пришли к проблеме - из кода сложно понять, что именно значит int fileSize. Довольно простым решением такой проблемы является использование постфиксов. 16 | Хранишь размер в мегабайтах? - fileSizeMb. 17 | В Гигабайтах? fileSizeGb. 18 | Сделал в UI выбор размера и единицы измерения? Жалко тебя. Именно в этот момент должно появится желание завести структуру из int и enum. 19 | На самом деле, проблема следует из постановки и решения, которое было изначально выбрано. Не был учтен тот факт, что типа int не достаточно для хранения размера. Не в плане границ значений, а как типа. Тип int - это примитив, который почти не имеет логики, но мы активно пытаемся ее на него натянуть. Через время появятся пачка конверторов, конверторов которые от енамов зависят, методы, которые для пользователей форматируют строку размера определенным образом. И все это, в лучшем случае будет одним большим статическим классом, которые как-то работает с int. 20 | 21 | ## Но если есть логика вокруг сущности - возможно стоит ввести свой тип? 22 | 23 | Описание отдельного типа позволяет определять логику работы с этим типом. Например, инкапсулировать логику создания. У типа будет возможность создаваться ссылаясь на два параметра - размер и единица измерения. Это позволит нам не забыть про конвертирование. У типа будет определен оператор + и - с этим же типом - ведь мы действительно можем сложить размеры двух файлов. Но операция MemorySize + int смысла не имеет. У типа можно определить набор нужных методов, таких как форматирование для пользовательского интерфейса. 24 | 25 | ![](img/img-2.jpg) 26 | 27 | Что мы в итоге получили от описания нового типа: 28 | - Семантика кода - вместо int используется тип, по которому можно понять предназначение, за какую логику отвечает 29 | - Типобезопасность - использование своего типа означает, что мы уже не можем так легко проворачивать операции сложения и умножения с любыми другими числовыми типами и это правильно с точки зрения логики. Для типа мы можем определить ограниченный набор операций и на уровне компилятора будет гарантироваться корректность выражений 30 | - Инкапсуляция преобразований - поместив все в свой тип, можно гарантировано хранить размер в байтах и определить методы получения значения в определенных единицах. Таким образом, в UI будет читаться из MemorySize в нужном формате, а вся остальная логика работает не зная о каких-либо преобразованиях. 31 | - Уменьшение вероятности дублирования - имея свой тип мы можем смело набивать его различными методами по работе с ним. Без него же мы бы писали в случайных местах статические приватные методы, которые было бы очень сложно отслеживать, и гарантировать, что такую же логику не сделали до вас - довольно сложно. 32 | 33 | ![](img/img-3.jpg) 34 | 35 | ## Итог 36 | 37 | Цель данного повествования отображена в заголовке — make type not classes. 38 | 39 | У вас есть логика работы с путями? Не насилуйте string, сделайте FilePath и все нужные методы работы с путями. 40 | 41 | Сложная логика фильтрации списка каких-то данных? Не пишите статических методов, разбросанных по всему проекту — напишите класс-холдер, который будет хранить контекст и иметь методы применения фильтрации. 42 | 43 | Для решение вашей задачи подходит примитивный тип? Класно, но может стоит задуматься о том, чтобы сделать код более читаемым? -------------------------------------------------------------------------------- /Learn/Articles/Starting-new-repository.md: -------------------------------------------------------------------------------- 1 | # Starting new repository 2 | 3 | Экосистема dotnet позволят очень легко создавать новые проекты и начинать писать код. Но со временем появляется всё больше нюансов, которые нужно не забывать во время старта очередного проекта. 4 | 5 | Чек лист: 6 | 7 | - Создать репозиторий в организации Kysect; 8 | - Склонировать репозиторий и создать в нём директорию `Source`; 9 | - В директории Source создать Blank solution с названием `Kysect.*RepositoryName*` (т.е. добавить префикс `Kysect.` к названию репозитория); 10 | - Скопировать актуальный .editorconfig с https://github.com/Kysect/CodeRules/ в директорию Source и добавить файл в sln; 11 | - Добавить в корень репозитория директорию `.github/workflows` и создать в ней конфигурацию для Github Action CI для запуска билда и тестов солюшена на пул реквестах; 12 | - Убедиться, что в корне репозитоиря лежит `.gitignore` для Visual studio и добавить его, если нет; 13 | - Добавить в созданные csproj конфигурацию для анализа - `True` и `True`; 14 | - Завести ишую на подключение SonarCloud анализа для репозитория; 15 | - Описать в `Readme.md` проект, его цель и особенности. 16 | -------------------------------------------------------------------------------- /Learn/Articles/Using-swagger-codegen.md: -------------------------------------------------------------------------------- 1 | # Swagger codegen 2 | 3 | ## Swaggr in a nutshell 4 | 5 | - Swagger (OpenAPI) — это не зависящая от языка спецификация для описания REST API. Она позволяет компьютерам и пользователям лучше понять возможности REST API без прямого доступа к исходному коду 6 | - Swagger UI - инструмент, который позволяет визуализировать спецификацию. Его можно разместить в ASP и получить возможность через него также вызывать существующие методы API. 7 | 8 | Почитать можно тут - https://docs.microsoft.com/ru-ru/aspnet/core/tutorials/web-api-help-pages-using-swagger. 9 | 10 | ## Client generation 11 | 12 | С использованием Swagger'а появляется возможность генерировать шаблонные клиенты для API. Один из вариантов - это использовать NSwagStudio. Важно понимать, что генерируется клиент по написанным контроллерам и DTO. При их смене нужно перегенерировать клиент. 13 | 14 | ### Процесс создания 15 | 16 | 1. Запустить [NSwagStudio](https://github.com/RicoSuter/NSwag/wiki/NSwagStudio) 17 | 2. Создать новый *\*.nswag* файл (File > New) 18 | 3. Выбрать нужный нам тип клиента (В дальнейшем тексте будет использоваться CSharp Client, так что некоторые пункты могут быть не актуальны для TypeScript) 19 | 20 | ![](https://i.imgur.com/n1qp8T1.png) 21 | 22 | 4. В настройках указать нужный нам Namespace и в самом низу в разделе Output указать путь, куда будет генерироваться клиент 23 | 5. По остальным настройкам: можно изучить самостоятельно и выбрать подходящие вам, большинство варьируется от ваших потребностей и предпочтений. Пример настройки можно посмотреть, открыв [этот](https://github.com/kysect/iwentys/blob/master/Source/Endpoints/Iwentys.Endpoints.Sdk/IwentysApiClient.nswag) файл в NSwagStudio 24 | 6. **Запустить бек** и посмотреть на каком порте он запустился 25 | 7. Во вкладке "OpenApi/Swagger Specification" в поле "Specification URL" ввести ссылку на спецификацию, она будет выглядеть примерно так ```https://localhost:44388/swagger/v1/swagger.json``` 26 | 8. Нажать "Create local" copy 27 | 9. Нажать "Generate Files", после чего по указанному ранее пути создастся клиент 28 | 10. Нажать Ctrl+S что бы сохранить nswag файл с конфигурацией клиента, в дальнейшем нужно будет просто обновлять его и перегенерировать клиент 29 | 30 | ### Процесс обновления: 31 | 32 | 1. Запустить [NSwagStudio](https://github.com/RicoSuter/NSwag/wiki/NSwagStudio) 33 | 2. Открыть в ней файл *\*.nswag*, он обычно находится в проекте SDK. 34 | 3. **Запустить бек** и посмотреть на каком порте он запустился 35 | 4. Во вкладке "OpenApi/Swagger Specification" удостовериться, что в поле "Specification URL" введена ссылка с правильным портом и нажать Create local copy 36 | 37 | ![](https://i.imgur.com/U3kCVIp.png) 38 | 39 | 5. Удостовериться, что в "Outputs" выбран нужный тип клиента ("CSharp Client"), после чего нажать "Generate Files" 40 | 6. Нажать Ctrl+S что бы сохранить обновлённый nswag файл 41 | 42 | 43 | ### Как этим вообще пользоваться 44 | 45 | Достаточно просто: создаём сгенерированный класс Client руками или череез DI контейнер. У него есть единственная зависимость - HttpClient. У HttpClient обязательно должно быть установлено поле BaseAddress - собственно адрес нашего сервера. В случае веб клиента его можно получить из класса ASP 46 | 47 |

48 | 49 | ```c# 50 | new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) } 51 | ``` 52 | 53 |

54 | 55 | Также его можно установить просто строкой. Итоговое создание клиента будет выглядеть примерно так: 56 | 57 | DI: 58 | 59 |

60 | 61 | ```c# 62 | builder.Services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); 63 | builder.Services.AddScoped(); 64 | ``` 65 | 66 |

67 | 68 | Ручками: 69 | 70 |

71 | 72 | ```c# 73 | var client = new Client(new HttpClient(){BaseAddress = new Uri("https://localhost:5001/")}); 74 | ``` 75 | 76 | Класс Client по сути дублирует методы нашего API, так что дальше можно просто вызывать нужные нам методы 77 | 78 |

79 | 80 | 81 | 82 | ## Возможные ошибки 83 | 84 | * **An error occured while sending the request** - Либо бек не запущен, либо введена неправильная Specification URL ![](https://i.imgur.com/VYfHDqG.png) 85 | -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Diagrams/Git-branches-stage-1.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | (Init) <-u- (C1) 4 | note left of C1 : master (before merge) 5 | (C1) <-r- (C2) 6 | (C2) <-u- (C3) 7 | note right of C3 : feat/new-feature 8 | 9 | (C1) <-u- (merge) 10 | (C3) <-l- (merge) 11 | note left of merge : master (after merge) 12 | 13 | @enduml -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Diagrams/Git-branches-stage-2.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | (Init) <-r- (C1) 4 | note right of C1 : dev (first commit) 5 | 6 | (C1) <-r- (C2) 7 | note right of C2 : feat/first-feature 8 | 9 | (C2) <-- (M1) 10 | 11 | (M1) <-r- (C3) 12 | note right of C3 : feat/second-feature 13 | 14 | (C3) <-l- (M2) 15 | 16 | (Init) <-u- (M3) 17 | (M2) <-u- (M3) 18 | 19 | @enduml -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic1.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic10.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic11.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic12.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic13.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic14.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic15.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic16.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic17.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic18.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic19.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic2.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic20.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic21.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic22.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic23.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic24.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic25.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic7.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/Pictures/pic8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Articles/Working-with-git/Pictures/pic8.png -------------------------------------------------------------------------------- /Learn/Articles/Working-with-git/README.md: -------------------------------------------------------------------------------- 1 | # Работа с Git + Github: Для самых маленьких 2 | 3 | - [Работа с Git + Github: Для самых маленьких](#работа-с-git--github-для-самых-маленьких) 4 | - [Система контроля версий](#система-контроля-версий) 5 | - [VCS для нескольких пользователей](#vcs-для-нескольких-пользователей) 6 | - [Репозитории](#репозитории) 7 | - [Github repository](#github-repository) 8 | - [Commits](#commits) 9 | - [Commits naming](#commits-naming) 10 | - [Commit author](#commit-author) 11 | - [Ignoring files in git](#ignoring-files-in-git) 12 | - [Branching](#branching) 13 | - [Base branch merge](#base-branch-merge) 14 | - [Pull request](#pull-request) 15 | - [Conflict](#conflict) 16 | - [Коммиты и ветки](#коммиты-и-ветки) 17 | - [Варианты работы с Git](#варианты-работы-с-git) 18 | - [GitKraken](#gitkraken) 19 | - [Альтернативный способ:](#альтернативный-способ) 20 | - [Visual Studio](#visual-studio) 21 | - [IDE от JetBrains](#ide-от-jetbrains) 22 | - [Что почитать](#что-почитать) 23 | 24 | ## Система контроля версий 25 | 26 | Система контроля версий (VCS) - это инструмент, который позволяет управлять изменениями. Для упрощения будем считать, что VCS работает с какой-то директорией и отслеживает изменения внутри неё - добавленные, изменённые или удалённые файлы и поддиректории (далее "объектов"). 27 | 28 | Базовые операции VCS: 29 | 30 | - Фиксация текущего состояния объектов. После фиксации в системе останется запись о том, в каком состоянии находился каждый объект; 31 | - Отслеживание изменений. VCS отслеживает и может предоставить информацию о том, как изменился объект сравнивая его с состояние в момент прошлой фиксации; 32 | - Откатывание изменений. VCS позволяет вернуться к состоянию последней фиксации откатив изменения; 33 | - Откатывание к прошлым фиксациям. VCS позволяет работать не только с последней фиксацией, но и возвращать состояние директории в момент любой существующей фиксации. 34 | 35 | Плюсы применения VCS: 36 | 37 | - Есть возможность увидеть изменения текущей итерации, провести ревью только новых изменений, а не всего кода; 38 | - Если во время изменения стало понятно, что всё пошло не туда и нужно откатиться, наличие фиксаций позволяют откатываться к определённому моменту, а не начинать всё с нуля; 39 | - Работая с кодом, можно вернуться в состояние в прошлом, запустить, посмотреть и сравнить; 40 | - VCS предоставляет историю фиксаций. В любой момент можно посмотреть когда и кем изменялся отдельно взятый файл или директория в целом. 41 | 42 | ### VCS для нескольких пользователей 43 | 44 | Основной сценарий использования VCS - это совместная работа над проектом многими пользователями одновременно. Есть два основных подхода: 45 | 46 | Централизованные VCS. Идея в том, что есть основной экземпляр VCS, где храниться информация о всех изменениях. Когда пользователю нужно начать работать с системой, он подключается к VCS, выгружает данные локально и начинает работать. Когда изменения локально внесены, пользователь отправляет основному экземпляру VCS запрос на фиксацию изменений. 47 | 48 | Децентрализованные VCS. Основное отличие в том, что пользователь получает возможность работать с VCS локально и независимо. Пользователь перед началом работы с VCS копирует себе всю метаинформацию об изменениях. В Децентрализованных VCS есть понятие репозиторий - это и есть этот набор файлов и метаданных. Пользователь может добавлять в свою копию репозитория фиксации. Синхронизация между пользователями происходит за счёт дальнейших слияний этих независимых репозиториев. У децентрализованных VCS обычно есть основной экземпляр, пользователи синхронизируют свои изменения с ним. 49 | 50 | ### Репозитории 51 | 52 | Далее под VCS будет подразумеваться git и примеры работы будут с использованием git'а. Git - это децентрализованная VCS. 53 | 54 | Репозитории можно поделить на две категории: 55 | 56 | - Local. Это репозиторий, с которым пользователь работает. Он был либо создан пользователем локально, либо был склонирован из другого репозитория; 57 | - Remote. Это репозитории, которые находятся на удалённой ноде, которая предоставляем возможность синхронизировать с ней репозиторий. Примером является GitHub - он даёт возможность создавать репозиторий на их серверах и с помощью HTTP запросов выполнять операции - клонирование remote repository (а значит создание локальной копии), синхронизация (ряд операций, который синхронизируют local и remote repositories). Важно понимать, что remote репозиторий ничем не отличается от local с точки зрения наполнения - это такой же набор файлов и метаданных идентичный тому, что получит пользователь при клонировании. 58 | 59 | Как получить local repository, который ассоциирован в remote: 60 | 61 | - Вариант 1. Создать локально директорию, инициализировать её как git repository (git init). После чего перейти в сервис, который предоставляет возможность загружать remote repository (GitHub, GitLab, Azure DevOps), получить ссылку на место для загрузки репозитория (это HTTP или SSH ссылка). После чего можно добавить в локальный репозиторий информацию о remote repository (git remote). 62 | - Вариант 2. Создать сначала ремоут репозиторий, склонировать его локально и работать с ним. 63 | 64 | После добавления remote репозитория в метаданных local репозитория будет хранится метаинформация и local и remote репозитория. Не смотря на то, что после добавления remote repository в local repository, они не синхронизируются автоматически. Может случиться такая ситуация, когда в local создаются коммиты и не попадают в remote или наоборот. Есть две основные операции для синхронизации: 65 | 66 | - push - это отправка коммитов из локального репозитория в remote 67 | - pull - это получение последней версии remote репозитория 68 | 69 | ### Github repository 70 | 71 | Про подробное устройство репозитория и то, как он работает внутри, можно почитать тут https://git-scm.com/book/ru/v2/ 72 | 73 | Github - соцсеть для программистов: тут можно легко передавать, хранить и получать самую актуальную информацию. 74 | 75 | Также на Github есть деление на private и public репозитории. Public репозитории доступны всем желающим, а Private только вам и тем, кому вы предоставите эту возможность. 76 | 77 | Для управления репозиторием на Github необходимо перейти во вкладку Settings 78 | ![](Pictures/pic13.png) 79 | 80 | Если вы хотите сделать репозиторий приватным\публичным или удалить его, скролльте вниз до Danger zone 81 | ![](Pictures/pic14.png) 82 | 83 | Если вы хотите добавить кого-то в приватный репозиторий, вам поможет вкладка manage access 84 | ![](Pictures/pic15.png) 85 | 86 | ## Commits 87 | 88 | Итак, у нас имеется настоящий Git-репозиторий и рабочая копия файлов для некоторого проекта. Нам нужно делать некоторые изменения и фиксировать эти изменения в вашем репозитории каждый раз, когда проект достигает состояния, которое нам хотелось бы сохранить. Каждая подобная фиксация является коммитом. 89 | 90 | Commit - это снимок текущего репозитория и набор метаданных, которые были сохранены во время создания. 91 | 92 | Не стоит пихать всё подряд в один огромный коммит - гораздо лучше разнести их на несколько коммитов поменьше, каждый из которых будет отвечать за то или иное изменение в проекте. 93 | 94 | Пример хорошего коммита 95 | 96 | ![](Pictures/pic11.png) 97 | 98 | Пример плохого коммита 99 | 100 | ![](Pictures/pic12.png) 101 | 102 | ### Commits naming 103 | 104 | Commit содержит message, который прописывается во время создания. Есть ряд рекомендаций, который стоит придерживаться при нейминге. Основные пункты: 105 | 106 | - Сообщение комита должно отображать сделанные изменения 107 | - Хорошо: `Fix queue ordering algorithm` 108 | - Плохо: `Close bug #12321` 109 | - Сообщение должно начинаться с "imperative present active verb" (c) 110 | - Хорошо: `Fix`, `Refactor`, `Optimize` 111 | - Плохо: `Refactoring`, `Fixed`, `Optimizes` 112 | - Сообщение должно начинаться с большой буквы 113 | - Не используйте точку в конце сообщения (только в гите (!)) 114 | - Не пишите сообщение больше 50 символов. Желание написать длинное сообщение может быть связано с попыткой закомитить сразу больше одного действия. Имеет смысл декомпозировать 115 | 116 | Сильно может помочь набор префиксов. Но стоит относиться к этому, как к примеру часто используемых префиксов: 117 | 118 | - Add feature for a user to like a post 119 | - Drop feature for a user to like a post 120 | - Fix association between a user and a post 121 | - Bump dependency library to current version 122 | - Make build process use caches for speed 123 | - Optimize search speed for a user to see posts 124 | - Document community guidelines for post content 125 | - Refactor user model to new language syntax 126 | - Reformat home page text to use more whitespace 127 | 128 | Что почитать: 129 | 130 | - Статьи по запросу "semantic commit message" 131 | - https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716 132 | - https://cbea.ms/git-commit/ 133 | 134 | Как могла бы выглядеть история случайно взятого репозитория: 135 | 136 | ``` 137 | Add entities for AW 138 | Add support for JOIN with WHERE 139 | Remove unused entities from serialization project 140 | Rename OrmTask to QueryData 141 | Document new library API 142 | Add new project for tests 143 | Reformat issue template 144 | Remove outdated to-do's 145 | Add support for ADO 146 | Refactor table join logic 147 | Fix missed brackets in alias 148 | ``` 149 | 150 | ### Commit author 151 | 152 | Помимо явно указанных данных (изменения и commit message) есть те, которые прописываются неявно. Например - имя и почта автора. Эта данные содержатся во всех коммитах, а данные берутся из конфигурации git'а. Явно задать значения можно командами: 153 | 154 | ``` 155 | git config --global user.name "FIRST_NAME LAST_NAME" 156 | git config --global user.email "MY_NAME@example.com" 157 | 158 | ``` 159 | 160 | Указывать правильную почту важно в том числе для того, чтобы GitHub мог сопоставлять коммиты с аккаунтов на GitHub'е. Это делается путём сопоставления почты автора в коммите и добавленных почт в аккаунт. 161 | 162 | ### Ignoring files in git 163 | 164 | Системы контроля версий используются для отслеживания файлов, которые имеют ценность для репозитория. Такими являются не все файлы. Примером не нужных в системе контроля версий файлов можно назвать сгенерированные временные файлы. Например, во время компиляции и запуска C# проектов создаются директории bin/ и obj/, они хранят в себе временные файлы. Чтобы эти файлы не попали в репозиторий, а их изменения не забивали diff в pull request'е, их нужно игнорировать в git'е. Для этого есть .gitignore. 165 | 166 | .gitignore - это специальный файл git'а, в котором можно указать список файлов и директорий, которые будут игнорироваться при трекинге изменений git'ом. Такой файл создаётся в корне git репозитория и применяется на него. Пример содержимого файла: 167 | 168 | ``` 169 | # Build results 170 | [Dd]ebug/ 171 | [Rr]elease/ 172 | [Bb]in/ 173 | [Oo]bj/ 174 | [Ll]ogs/ 175 | 176 | *.db 177 | ``` 178 | 179 | Указанные в примере строчки в этом файле будут указывать git'у на то, что нужно игнорировать директории `Debug`, `Obj`, а также любые файлы с расширением `.db`. Обычно такой файл IDE генерирует при создании проекта. Если же файл не сгенерировался, можно найти примеры под нужную платформу и IDE и создать его самостоятельно. В репозитории https://github.com/github/gitignore лежат примеры gitignore файлов для различных языков, платформ и IDE. Оттуда можно скопировать пример для Visual studio и положить в корень проекта. 180 | 181 | Но если так сложилось, что файлы уже попали в commit (не было в проекте .gitignore, закомитили изменения и потом добавили), то добавление .gitignore'а не приведёт к удалению и более того, файлы будут продолжать отслеживаться git'ом. Чтобы избавиться от таких файлов нужно: 182 | 183 | 1. Закрыть IDE и другие приложения, которые могут удерживать файлы или их генерировать; 184 | 2. Найти нужный .gitignore, добавить его в корень директории с репозиторием, закомитить; 185 | 3. Удалить все директории и файлы, которые не должны быть в git'е и закомитить изменения; 186 | 4. Убедиться, что при открытии IDE, компиляции и других действиях удалённые файлы не попадают в трекинг git'а 187 | 188 | Дополнительный hard mode: для того, чтобы не только в будущем, а ещё и в прошлом не сталкиваться с не нужными файлами, можно воспользоваться git командами для удаления изменения из старых комитов - git filter-branch. Но стоит помнить, что изменения комита в прошлом - это буквально пересоздание его, а значит нужно будет делать force push, а изменения будут несовместимы с тем, что в параллель могли делать коллеги. И всегда есть возможность случайно убить всю историю. 189 | 190 | 191 | ## Branching 192 | 193 | Ветки в git - это специальным образом сохранённые ссылки на определённый коммит. 194 | 195 | Ветки в git позволяют создавать комиты изолированно от остальных веток. В дальнейшем можно между этими ветками переключатся сохраняя в каждой ветке тот стейт до которого разработка дошла. При создании репозитория, в нём автоматически создаётся основная ветка - master, которая может быть использована для фиксации изменений. Это достаточно, чтобы создавать новые коммиты и вести работу, но с ростом размера проекта и команды это становится не удобно. Какой именно подход по использованию веток выбрать зависит от размеров команды, проекта зависит и принятого workflow зависит. 196 | 197 | Этап 1. В процессе разработки появится необходимость в ревью, CI и остальном. Чтобы реализовать накую возможность, нужно создавать отдельную ветку, чтобы от неё создавать pull request. В этот момент появляется необходимость в feature-ветках. Это такие ветки, которые создаются под написание одной новой фичи, одного изменений etc. Их время жизни заканчивается после мёрджа ветки в master. Такие ветки можно называть `feat/your-feature-name`. Аналогично можно сказать про фиксы. 198 | 199 | Этап 2. По мере усложнения продукта и увеличения размера цикла разработки, появляется необходимость иметь стабильную ветку, с которой можно взять рабочую версию. Проблема в том, что изменения, которые вливаются с feature-веток, могут быть недостаточно протестированы. В такой ситуации имеет смысл выделить dev-ветку. Эта ветка будет использоваться во время разработки, в неё будут вливаться изменения. После того, как все нужные изменения влиты и протестированы, ветка dev вливается в мастер. 200 | 201 | Этап 3. Есть сценарии, которые не вписываются в модель с master + dev ветками. Самый частых из них - это необходимость загрузить hotfix в master. Но если делать это через dev ветку, то могут попасть остальные изменения, которые нужно детально тестировать. Чтобы сократить время и исправить проблему ASAP вводят hotfix ветки, которые после верификации вливаются в master и dev ветки. 202 | 203 | Этап 4. Если в проекте много разработчиков и они параллельно ведут работают над проектом, то в какой-то момент часть из них будет занята стабилизацией ветки dev и её подготовкой к слиянию. В то же время остальные будут продолжать разработку и вносить новые изменения в dev, тем самым усложняя работу первой группе. Чтобы избежать такой проблемы, имеет смысл выделить ветку release. Как только работы над веткой dev заканчиваются, от последнего комита создаётся ветка release и в ней происходит закрытие проблем и багой, которые мешают влить ветку dev в ветку master. Как только все проблемы устранены, ветка release вливается в master и в dev (он за время существования ветки release там могли появиться коммиты). 204 | 205 | ### Base branch merge 206 | 207 | Рассмотрим частую ситуацию при разработке и использованием веток. В проекте существовала ветка master, от неё отбранчили две feature-ветки - feature-a и feature-b, в них начали создаваться коммиты. После этого ветку feature-a доделали и вмёрджили в master, а в ветке feature-b появилась необходимость использовать изменения из feature-a. Есть два варианта решения проблемы: 208 | 209 | - rebase - перенести изменения feature-b на последний коммит мастера после мёрджа 210 | - merge master to feature-b - смёрджить изменения из ветки master в ветку, где этих изменений не хватает. Это не соответствует обычному workflow мёрджа, но такой мёрдж позволяет синхронизировать feature-ветку с её base-веткой. 211 | 212 | ### Pull request 213 | 214 | Pull request - это механизм, который выходит за рамки git, но он есть во всех сервисах управления репозиториями (GitHub, Azure DevOps). Pull request - это запрос на влитие одной ветки в другую. Хорошим тоном является закрытие возможности делать push коммитов в master и единственным способом залить туда коммиты - это создание pull request'а. Pull request - это этап между созданием коммита и его попадания в мастер ветку, который позволяет задавать правила для merge операции: 215 | 216 | - Возможность сконфигурировать GitHub Action и запускать билд и проверку всех тестов 217 | - Возможность сконфигурировать GitHub Action и запускать анализатор кода (например, SonarCloud) 218 | - Возможность повесить требование на обязательное ревью перед merge 219 | 220 | Если эти требования не соблюдаются, то GitHub не будет давать возможности выполнить pull request merge. 221 | 222 | ### Conflict 223 | 224 | При параллельной работе с репозиторием может оказаться ситуация, когда два pull request'а меняют одинаковые строчки. Система контроля версий не может за пользователя решить, какую именно строчку нужно в итоге загрузить и называет такую ситуацию merge conflict. Если работать с репозиторием через pull request, то информация о конфликте появится в самом PR и будет заблокирована возможность выполнить merge. Решением этой проблемы является ручной резолв конфликтов: 225 | 226 | 1. Открыть локально репозиторий, сделать pull ветки от своего PR'а и ветки master 227 | 2. Выполнить checkout ветки от PR 228 | 3. Выполнить merge ветки master в текущую ветку 229 | 4. Получить сообщение о конфликте и вручную выбрать какие изменения с каких веток должны попасть 230 | 5. Закомитить изменения, которые были внесены во время мёрджа 231 | 6. Выполнить push своей ветки, чтобы обновления попали в PR 232 | 233 | После этих действий ветка PR'а и master будут синхронизированы и конфликтов не будет. 234 | 235 | ### Коммиты и ветки 236 | 237 | Чтобы лучше использовать git, стоит чуть глубже разобраться в том, что именно за действия происходит во время выполнения git операций. 238 | 239 | Во время создания репозитория создаётся первый коммит. Первый созданный коммит содержит только снимок и набор метаданных. Также создаётся master ветка, которая на этот коммит ссылается. 240 | 241 | Каждый следующий коммит создаётся относительно прошлого коммита. В созданном новом коммите сохраняется ссылка на прошлый коммит, он считается родительским. При создании коммита также модифицируется и ветка. Коммит создаётся в активной ветке, относительно последнего коммита этой ветки. После создания нового коммита ветка начнёт ссылаться на новый созданный коммит - происходит перенос ссылки на новый коммит. 242 | 243 | Выполнение мёрджа также создаёт коммит. Если выполняется мёрдж ветки A в ветку B, то в ветке B создаётся новый коммит у которого будут записано два родительских коммита. 244 | 245 | Что делать, если коммит был создан не в той ветке? Например, пользователь забыл создать feature-ветку и создался коммит в ветке master. В первую очередь, строит вспомнить, что ветки - это ссылки на коммиты. На созданном комите можно создать новую ветку (т.е. ссылку). После создания новой ветки на созданном коммите остаётся проблема того, что ветка master также ссылается на этот коммит. Это решается тем, что в гите есть возможность двигать ветки между коммитами. Они всё ещё являются просто ссылками. Можно выполнить hard reset ветки мастер на прошлый коммит и тем самым откатить ветку назад. Порядок действий: 246 | 247 | 1. Осознать проблему 248 | 2. Создать ветку на последнем коммите 249 | 3. Выполнить checkout на ветку master 250 | 4. Выполнить reset мастера на прошлый коммит 251 | 5. Вернуться обратно на feature-ветку 252 | 253 | Но что же делать, если коммит уже запушился в remote repository? После выполнения reset remote ветка не будет обновлена, её нужно запушить. Но стоит понимать, что push удаления коммита - это потенциальное нарушение дерева. GitHub будет предупреждать, что так делать не стоит, что выполнить это можно только помощью force push. 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | ## Варианты работы с Git 263 | Для новичков я рекомендую использовать **GUI GitKraken** (https://www.gitkraken.com/), это тот же консольный Git, но только в красивой и интуитивно понятной оболочке. Однако при желании можно воспользоваться встроенными средствами IDE. 264 | 265 | ### GitKraken 266 | Для работы с Git первым делом необходимо создать репозиторий. 267 | 268 | ![](Pictures/pic1.png) 269 | 270 | Далее нам необходимо выбрать Github и создать наш репозиторий. **Обратите внимание на настройки доступа**: закрытый репозиторий (private) и открытый (public). Также стоит обратить внимание на **gitignore файл**, он должен соответствовать вашей **среде разработки** (в моём случае - Visual Studio). 271 | 272 | Не забываем о .gitignore! 273 | 274 | ![](Pictures/pic2.png) 275 | 276 | Кидаем проект в **папку с репозиторием**, папка должна выглядеть примерно так 277 | ![](Pictures/pic7.png) 278 | 279 | В самом GitKraken'e справа **должны появиться изменения**, из всех файлов важными оказались только 3, значит gitignore сработал правильно, называем и делаем commit 280 | 281 | ![](Pictures/pic8.png) 282 | 283 | Ну вот мы и пришли к последнему этапу: дело в том, что при создании коммита мы никуда ничего не отправили, изменения сохранились только на нашем локальном компьютере, то есть никаких изменений в репозиторий на Github'e мы не внесли. Для того, чтобы наши изменения появились в репозиторие на Github'e, необходимо в клиенте GitKraken'a нажать кнопку **Push.** 284 | 285 | На этом всё, далее вы можете работать над вашим проектом. GitKraken будет сам отслеживать изменения в коде, необходимо только делать Commit+Push для обновления информации на Github 286 | 287 | ## Альтернативный способ: 288 | 289 | Конечно же, есть и другие способы создания репозитория. Например, можно создать проект в Visual Studio с локальным гитом 290 | (мануал как это сделать https://vk.cc/azdQtZ) 291 | 292 | Далее открываем папку с проектом через GitKraken и делаем remote 293 | 294 | ![](Pictures/pic10.png) 295 | 296 | Делаем уже привычные commit+push, и наши файлы теперь лежат на github 297 | 298 | ### Visual Studio 299 | Итак, по какой-либо причине вы отказались от удобного UI и решили пользоваться встроенными средствами Visual Studio. 300 | Вы работали над проектом и в какой-то момент решили добавить git репозиторий? Нет проблем - жмите на эту кнопку (да, у автора русская Visual Studio, и да, однажды он это исправит) 301 | ![](Pictures/pic18.png) 302 | 303 | После этого вам будет предложено выбрать его настройки приватности, имя и месторасположение. Кроме того, если вы синхронизировались со своим аккаунтом на Github, у вас будет возможность автоматически создать репозиторий и там. 304 | ![](Pictures/pic19.png) 305 | 306 | Кроме того, в "шапке" доступна следующая вкладка. В ней мы можем сделать коммит, запушить изменения на Github, получить чужие изменения и перейти в управление ветками 307 | 308 | ![](Pictures/pic20.png) 309 | 310 | После клика на "фиксация"/"commit" открывается следующее окошко. В нём мы и создаем наш коммит, после чего его можно запушить, нажав на соответствующую кнопку. 311 | 312 | ![](Pictures/pic21.png) 313 | ### IDE от JetBrains 314 | Во всех IDE от JetBrains работа с git устроена одинаковым образом. Мы же рассмотрим её на примере работы с Rider. 315 | 316 | При создании проекта вам будет предложено автоматически создать git репозиторий. Если не ставить галочку, это можно будет сделать позднее во вкладке git. 317 | ![](Pictures/pic22.png) 318 | 319 | Для взаимодействия с git-oм непосредсвенно изнутри IDE нам понадобятся следующие кнопки. 320 | Синяя стрелочка (Pull) - выгрузить изменения из удалённого репозитория. 321 | Зелёная галочка (Commit) - сделать коммит. 322 | Зелёная стрелочка (Push) - запушить коммит на удалённый репозиторий. 323 | ![](Pictures/pic23.png) 324 | 325 | Кроме того, Intellij idea предоставляет относительно удобную работу с ветками, если вы по каким то причинам не хотите устанавливать Gitkraken. После клика на Branches во вкладке Git, перед нами появится следующее окошко, в котором мы можем создавать новые ветки (New branch), переходить между ветками (Checkout branch) и делать прочие непотребства 326 | 327 | ![](Pictures/pic24.png) 328 | 329 | Также по клику на вкладку Git в правом нижнем углу экрана (она появится только если у вас уже есть Git репозиторий) можно открыть окошко с отрисовкой веток и возможностью перемещения по коммитам. 330 | 331 | ![](Pictures/pic25.png) 332 | 333 | ## Что почитать 334 | 335 | https://git-scm.com/book/ru/v2/ (Всё о гите) 336 | 337 | https://support.gitkraken.com/start-here/guide/ 338 | 339 | https://rogerdudler.github.io/git-guide/ (микрогайд по консольному гиту) 340 | 341 | https://tproger.ru/translations/beginner-git-cheatsheet/ 342 | -------------------------------------------------------------------------------- /Learn/Books/Book-guide.puml: -------------------------------------------------------------------------------- 1 | @startuml Bookshelf 2 | 3 | skinparam component { 4 | Style rectangle 5 | } 6 | 7 | component "C# Basic" as CSharp_Basic { 8 | component "The Object-Oriented Thought Process \nBy Matt Weisfeld" as Object_Oriented 9 | component "C# 12 and .NET 8 \nBy Mark J. Price" as Price 10 | component "Pro C# 10 with .NET 6 \nBy Andrew Troelsen" as Troelsen 11 | component "C# 12 in a Nutshell \nBy Joseph Albahari" as Albahari 12 | 13 | Object_Oriented -d-> Price 14 | Price <.l.> Troelsen 15 | Price <.r.> Albahari 16 | } 17 | 18 | component "Code design" as Code_design { 19 | component "Programming with Types \nBy Vlad Riscutia" as Programming_with_Types 20 | component "Clean Code \nBy Robert C. Martin" as Clean_code 21 | component "Unit Testing Principles, Practices, and Patterns \nBy Vladimir Khorikov" as Unit_testing 22 | component "Dependency Injection Principles, Practices, and Patterns \nBy Steven van Deursen" as Dependency_injection 23 | component "Паттерны проектирования на платформе .NET \nBy Sergey Teplyakov" as Patterns 24 | component "Category Theory for Programmers \nBy Bartosz Milewski" as Category_Theory 25 | 26 | Programming_with_Types --> Clean_code 27 | Clean_code --> Unit_testing 28 | Unit_testing --> Dependency_injection 29 | Clean_code --> Patterns 30 | Programming_with_Types --> Category_Theory 31 | } 32 | 33 | component "Code Architecture" as Code_Achitecture { 34 | component "Clean Architecture \nBy Robert C. Martin" as Clean_Architecture 35 | component "Microsoft .NET: Architecting Applications for the Enterprise \nBy Dino Esposito" as Microsoft_NET 36 | component "Implementing Domain-Driven Design \nBy Vaughn Vernon" as DDD 37 | 38 | Clean_Architecture --> Microsoft_NET 39 | Microsoft_NET --> DDD 40 | } 41 | 42 | component ".NET" as NET_Internals { 43 | component "Concurrency in C# Cookbook \nBy Stephen Cleary" as Cleary 44 | component "Pro .NET Memory Management \nBy Konrad Kokosa" as Memory_Management 45 | component "Pro .NET Benchmarking \nBy Andrey Akinshin" as Benchmarking 46 | component "Exploring the .NET Core 3.0 Runtime \nBy Roger Villela" 47 | component "Pro .NET Framework with the Base Class Library \nBy Roger Villela" 48 | component "Apps and Services with .NET 8 \nBy Mark J. Price" 49 | 50 | Cleary --> Benchmarking 51 | Cleary --> Memory_Management 52 | } 53 | 54 | component "Self dev" as Soft_skills { 55 | component "Clean Coder \nBy Robert C. Martin" as Clean_Coder 56 | component "Clean Craftsmanship \nBy Robert C. Martin" as Clean_Craftsmanship 57 | component "The Pragmatic Programmer \nBy Andrew Hunt" as Pragmatic_Programmer 58 | 59 | Clean_Coder --> Clean_Craftsmanship 60 | Clean_Craftsmanship --> Pragmatic_Programmer 61 | } 62 | 63 | component "Project management" as Project_management { 64 | component "Creating Software with Modern Diagramming Techniques \nBy Ashley Peacock" as Diagrams 65 | component "UML Distilled \nBy Martin Fowler" as UML 66 | 67 | component "Code Ahead \nBy Yegor Bugayenko" as Code_Ahead 68 | component "Clean Agile: Back to Basics \nBy Robert C. Martin" as Clean_Agile 69 | component "Software Engineering at Google \nBy Titus Winters" as Software_Engineering_at_Google 70 | component "Continuous Delivery \nBy Jez Humble" as Continuous_Delivery 71 | component "Righting Software \nBy Juval Löwy" as Righting_Software 72 | component "Software Requirements \nBy Karl Wiegers" as Software_Requirements 73 | 74 | Diagrams --> UML 75 | Code_Ahead --> Clean_Agile 76 | Clean_Agile --> Software_Engineering_at_Google 77 | Software_Engineering_at_Google --> Continuous_Delivery 78 | Software_Engineering_at_Google --> Righting_Software 79 | } 80 | 81 | Price --> Clean_code 82 | Dependency_injection --> Clean_Architecture 83 | Price --> Cleary 84 | Pragmatic_Programmer --> Code_Ahead 85 | 86 | @enduml 87 | -------------------------------------------------------------------------------- /Learn/Books/Books.md: -------------------------------------------------------------------------------- 1 | # Books 2 | 3 | Небольшая подборка книг, которые мы можем порекомендовать к ознакомлению. 4 | 5 | ## C# Basic 6 | 7 | - The Object-Oriented Thought Process By Matt Weisfeld 8 | - Описание: Данная книга начинается с самых базовых понятий в мире ООП, формирует представление о том, что такое типы, как они работают и из чего они состоят. Также книга содержит информацию о паттернах проектирования и SOLID. 9 | - Для кого: От 0 до Джуна. Для тех, кто уже освоился с основами лучше взять более профильные книги. 10 | 11 | - "C# 12 and .NET 8", "Pro C# 10 with .NET 6", "C# 12 in a Nutshell" 12 | - Описание: Три книги трёх разных авторов, которые очень сильно пересекаются и выбор между ними во многом вкусовщина 13 | - Для кого: Для тех, кто умеет использовать базовые C# конструкции и нуждается в более глубоком понимании языка и платформы. В качестве справочников подойдёт даже опытным разработчикам. 14 | 15 | ## Code design 16 | 17 | - Programming with Types By Vlad Riscutia 18 | - Описание: Книга о том, как использовать типы. Начиная от концепции типизации, продолжая Primitive Obsession, обобщёнными типами и заканчивая математическими типами. 19 | - Для кого: Рекомендуется прочитать всем. Часто разработчики недооценивают важность типов и эта книга позволит сдвинуться дальше в понимании. Для тех, кто уже нашёл общий язык с типами это будет отличной структуризацией, книжкой для референса и первым шагом к математическим типам и книге Бартоша Милевского. 20 | - Clean Code 21 | - Описание: Книга о том, как писать чистый код. Она содержит множество практических советов и примеров, которые оформлены в виде правил Do and Don't, так что их можно as is добавлять в code style. 22 | - Для кого: В первую очередь это книга для начинающих разработчиков и тех, кто хочет для себя подсветить новые возможные улучшения в своём подходе к коду. Для опытных разработчиков эта книга поможет структурировать свои внутренние "я так чувствую" и упростит превращение внутреннего чувства прекрасного в кодстайл. 23 | - Unit Testing Principles, Practices, and Patterns By Vladimir Khorikov 24 | - Описание: Несмотря на название, книга не только о юнит-тестировании. В данной книге рассказывается о решении одной из главных проблем тестирования - работа с зависимостями. 25 | - Для кого: Рекомендуется прочитать всем. 26 | - Dependency Injection Principles, Practices, and Patterns By Steven van Deursen 27 | - Описание: Книга развенчивает мифы о DI, идеально для тех, кто думает, что DI - это использование контейнеров. Во многом дополняет книгу Хорикова. 28 | - Для кого: Рекомендуется прочитать всем. 29 | - Паттерны проектирования на платформе .NET \nBy Sergey Teplyakov 30 | - Описание: Классическая книга по паттернам, охватывающая большую часть необходимых знаний по паттернам. После прочтения может выступать справочником. 31 | - Для кого: Рекомендуется прочитать всем. 32 | - Category Theory for Programmers By Bartosz Milewski 33 | - Описание: Это книга _не про программирование_. Она буквально про теорию категорий. Но это отличный пример знаний математики, которые заставят пересмотреть понимание кода, его структуры. 34 | - Для кого: Для тех, кто морально готов к математике и хочет улучшить качество своего кода. 35 | 36 | ## Code Architecture 37 | 38 | - Clean Architecture By Robert C. Martin 39 | - Описание: Книга о том, как строить архитектуру кода, писать расширяемый код, который будет легко поддерживать и тестировать. 40 | - Для кого: Рекомендуется прочитать всем, кто уже дошёл до задач, когда нужно проектировать больше 5 сущностей. 41 | - Microsoft .NET: Architecting Applications for the Enterprise \nBy Dino Esposito 42 | - Описание: Книга описывает основные элементы архитектуры приложений и как их писать на платформе .NET. 43 | - Для кого: Рекомендуется прочитать всем, кто сталкивается с архитектурой приложений, клиент-серверными приложениями и т.п. 44 | - Implementing Domain-Driven Design By Vaughn Vernon 45 | - Описание: Книга содержит много практических примеров и рекомендаций по проектированию сложного домена. 46 | - Для кого: Для разработчиков, которым требуется проектировать сложные домены. 47 | 48 | ## .NET 49 | 50 | - Concurrency in C# Cookbook By Stephen Cleary 51 | - Описание: Основы конкурентности в .NET. 52 | - Для кого: Рекомендуется прочитать всем. 53 | - Pro .NET Memory Management By Konrad Kokosa 54 | - Описание: Одна из лучших (и актуальная, в отличие от Рихтера) книг о том, что происходит внутри .NET. Книга покрывает не только работу с памятью, но и GC, особенности работы .NET Runtime. 55 | - Для кого: Для желающих погрузиться во внутренности .NET и тех, кто хочет научиться лучше работать с памятью. Но порог вхождения довольно высокий. 56 | - Pro .NET Benchmarking By Andrey Akinshin 57 | - Описание: Главная книга из мира бенчмаркинга. В ней содержатся не только рекомендации по использованию BenchmarkDotNet (основной библиотеки для бенчмаркинга в .NET), но и большое количество теории по статистике и анализу результатов. 58 | - Для кого: Для тех, кто много занимается профилированием и оптимизацией кода. 59 | - Exploring the .NET Core 3.0 Runtime, Pro .NET Framework with the Base Class Library By Roger Villela 60 | - Описание: Две книги, которые описывают BCL и Runtime .NET. Эти книги 61 | - Для кого: Для разработчиков, которые хотят погрузится во внутренности .NET. 62 | - Apps and Services with .NET 8 By Mark J. Price 63 | - Описание: Книга даёт краткий обзор различных технологиям и библиотекам, которые используются в .NET: ASP, Blazor, gRPC, GraphQL, SignalR. 64 | - Для кого: Для разработчиков, которые хотят расширить свои знания о платформе, ознакомиться с новыми технологиями, которые часто используются в .NET. Это позволит понять различные концепции, которые могут быть адаптированы даже в те проекты, где не используются напрямую эти технологии. 65 | 66 | ## Self development and soft skills 67 | 68 | - Clean Coder, Clean Craftsmanship By Robert C. Martin, The Pragmatic Programmer By Andrew Hunt 69 | - Описание: Эти книги содержат в себе огромное количество опыта, которое накопили авторы за время своей карьеры. Данные книги - это хороший способ не ждать, пока самому придётся столкнуться с проблемами, а заранее подготовиться к ним. В книгах освещаются вопросы коммуникации, командой работы, тестирования, планирования, оценки, подходам к работе 70 | - Для кого: Рекомендуется прочитать всем. 71 | 72 | ## Project management 73 | 74 | - Creating Software with Modern Diagramming Techniques By Ashley Peacock 75 | - Описание: Важные части управления проектом - это управление знаниями, фиксация договорённостей, шаринг информации между участниками. И все эти пункты тесно связаны с диаграммами. Данная книга содержит минимальный набор информации о диаграммах, поможет применять их в повседневной работе для тривиальных сценариев. Является отправной точкой для более глубокого ознакомления с диаграммами. 76 | - Для кого: Рекомендуется прочитать всем, кто ещё не знаком с диаграммами (т.е. не читал UML Distilled). 77 | - UML Distilled By Martin Fowler 78 | - Описание: Полноценный свод знаний по UML, который описывает стандарты, типы диаграмм, их назначение и применение. Позволит расширить арсенал инструментов и подходов к диаграммам, чтобы под специфические задачи выбирать более подходящие инструменты. 79 | - Для кого: Рекомендуется для тех, кому приходится часто сталкиваться с диаграммами и кому нужно улучшить их качество. 80 | - Code Ahead By Yegor Bugayenko 81 | - Описание: Данная книга написана в формате рассказа, где главный герой описывает свой опыт работы в новой команде, выявления проблем в управлении проектом. Книга легко читается и является хорошим первым шагом для знакомства с принципами управления проектами. 82 | - Для кого: Для тех, кто хочет начать делать первые шаги в управлении проектами и процессами. 83 | - Clean Agile: Back to Basics By Robert C. Martin 84 | - Описание: Книга описывает принципы Agile, и опыт их применения в различных проектах. 85 | - Для кого: Для тех, кто хочет начать делать первые шаги в управлении проектами и процессами. 86 | - Software Engineering at Google By Titus Winters 87 | - Описание: Книга содержит множество глав, которые описывают различные процессы и подходы к разработке ПО в Google. Хорошо подходит для ознакомления с основными процессами в проектах, их назначение и применение. 88 | - Для кого: Для тех, кто хочет ознакомиться с процессами разработки ПО, узнать как это делается в крупных компаниях. 89 | - Continuous Delivery By Jez Humble 90 | - Описание: Книга про CI/CD, описывает принципы, подходы и практики, которые позволяют ускорить процесс разработки и улучшить качество кода средствами автоматизации и процессов. 91 | - Для кого: Для тех, кто занимается управлением процессами разработки и хочет улучшить их. 92 | - Righting Software By Juval Löwy 93 | - Описание: Первая часть книги описывает дизайн системы: как выделять компоненты, как декомпозировать большую систему на отдельные разрабатываемые модули. А вторая часть книг описывает дизайн проекта: как планировать, оценивать, выстраивать план и порядок разработки, оценивать сложность, стоимость и риски. 94 | - Для кого: Для разработчиков, которым приходится сталкиваться с задачами проектирования и управления проектами или большими модулями, их оценкой, декомпозицией, выстраиванием процесса разработки. 95 | - Software Requirements By Karl Wiegers 96 | - Описание: Книга описывает процесс сбора и анализа требований к ПО, их документирование и управление. Книга содержит множество практических советов и примеров, которые помогут улучшить процесс сбора и анализа требований. Данная книга не является книгой по разработке. Но она поможет разработчика улучшить понимание требований и улучшить коммуникацию с аналитиками. 97 | - Для кого: Разработчиков, которые занимаются работой с требованиями, коммуникацией с аналитиками, реализацией сложных требований. 98 | -------------------------------------------------------------------------------- /Learn/Roadmap/Roadmap.md: -------------------------------------------------------------------------------- 1 | ![Roadmap](roadmap.png) 2 | 3 | # Map 4 | 5 | ## Tools Tools, IDE, git 6 | 7 | - Visual Studio, инфа про разные сборки и просто компоненты 8 | - Установка Visual Studio [link](https://docs.microsoft.com/ru-ru/visualstudio/install/install-visual-studio?view=vs-2019) 9 | - Гайд по VS, создание проекта [link](https://docs.microsoft.com/ru-ru/visualstudio/get-started/csharp/visual-studio-ide?view=vs-2019) 10 | - Немного про .Net [Метанит](https://metanit.com/sharp/tutorial/1.1.php) 11 | - Welcome to Github 12 | - [Общие сведения об управлении версиями с помощью Git](https://docs.microsoft.com/ru-ru/learn/paths/intro-to-vc-git/) 13 | - [introduction-to-github](https://docs.microsoft.com/en-us/learn/paths/collaborate-markdown-github-pages/) 14 | - [Manage the lifecycle](https://docs.microsoft.com/en-us/learn/paths/manage-project-lifecycle-github/) 15 | - [Collaborate with others with Markdown and GitHub Pages](https://docs.microsoft.com/en-us/learn/paths/collaborate-markdown-github-pages/) 16 | - [Git action CI](https://docs.microsoft.com/en-us/learn/paths/automate-workflow-github-actions/) 17 | 18 | # C# base 19 | 20 | Документация по языку от майкрософта: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/ 21 | 22 | - [csharp-first-steps](https://docs.microsoft.com/ru-ru/learn/paths/csharp-first-steps/) 23 | - [csharp-logic](https://docs.microsoft.com/ru-ru/learn/paths/csharp-logic/) 24 | - [csharp-data](https://docs.microsoft.com/ru-ru/learn/paths/csharp-data/) 25 | 26 | Немного про: 27 | - Перечисления enum [(Метанит)](https://metanit.com/sharp/tutorial/2.12.php) 28 | - Кортежи [(Метанит)](https://metanit.com/sharp/tutorial/2.19.php) 29 | - Анонимные типы [(Метанит)](https://metanit.com/sharp/tutorial/3.20.php) 30 | - Pattern matching [(Метанит)](https://metanit.com/sharp/tutorial/3.34.php) 31 | - Nullable-типы [(Метанит)](https://metanit.com/sharp/tutorial/2.17.php) 32 | - Строки 33 | - Форматирование и интерполяция строк [(Метанит)](https://metanit.com/sharp/tutorial/7.5.php) 34 | - Класс StringBuilder [(Метанит)](https://metanit.com/sharp/tutorial/7.3.php) 35 | - Структура DateTime 36 | - Структура DateTime [(Метанит)](https://metanit.com/sharp/tutorial/19.1.php) 37 | - Форматирование дат и времени [(Метанит)](https://metanit.com/sharp/tutorial/19.2.php) 38 | 39 | ## Введение в ООП. Типы: классы, структуры 40 | 41 | - Классы, Структуры, ссылочные и значимые типы 42 | - Классы [(Метанит)](https://metanit.com/sharp/tutorial/3.1.php) 43 | - Структуры [(Метанит)](https://metanit.com/sharp/tutorial/2.13.php) 44 | - Типы значений и ссылочные типы [(Метанит)](https://metanit.com/sharp/tutorial/2.16.php) 45 | - Особенности типов 46 | - Модификаторы доступа [(Метанит)](https://metanit.com/sharp/tutorial/3.2.php) 47 | - Свойства и инкапсуляция [(Метанит)](https://metanit.com/sharp/tutorial/3.4.php) 48 | - Перегрузка методов [(Метанит)](https://metanit.com/sharp/tutorial/3.5.php) 49 | - Статические члены и модификатор static [(Метанит)](https://metanit.com/sharp/tutorial/3.6.php) 50 | - Константы и поля для чтения [(Метанит)](https://metanit.com/sharp/tutorial/3.3.php) 51 | - Перегрузка операторов [(Метанит)](https://metanit.com/sharp/tutorial/3.36.php) 52 | - Значение null [(Метанит)](https://metanit.com/sharp/tutorial/3.26.php) 53 | - Индексаторы [(Метанит)](https://metanit.com/sharp/tutorial/4.10.php) 54 | - Основные механики ООП 55 | - Наследование [(Метанит)](https://metanit.com/sharp/tutorial/3.7.php) 56 | - Преобразование типов [(Метанит)](https://metanit.com/sharp/tutorial/3.11.php) 57 | - Перегрузка операций преобразования типов [(Метанит)](https://metanit.com/sharp/tutorial/3.37.php) 58 | - Виртуальные методы и свойства [(Метанит)](https://metanit.com/sharp/tutorial/3.19.php) 59 | - Сокрытие [(Метанит)](https://metanit.com/sharp/tutorial/3.41.php) 60 | - Абстрактные классы и члены классов [(Метанит)](https://metanit.com/sharp/tutorial/3.8.php) 61 | - Класс System.Object и его методы [(Метанит)](https://metanit.com/sharp/tutorial/3.10.php) 62 | - Интерфейсы [(Метанит)](https://metanit.com/sharp/tutorial/3.9.php) 63 | 64 | ## Коллекции, обобщения, LINQ 65 | 66 | - Обобщения 67 | - Обобщения [(Метанит)](https://metanit.com/sharp/tutorial/3.12.php) 68 | - Ограничения обобщений [(Метанит)](https://metanit.com/sharp/tutorial/3.38.php) 69 | - Коллекции 70 | - Введение в коллекции [(Метанит)](https://metanit.com/sharp/tutorial/4.1.php) 71 | - Обобщенные коллекции [(Метанит)](https://metanit.com/sharp/tutorial/4.4.php) 72 | - Список List [(Метанит)](https://metanit.com/sharp/tutorial/4.5.php) 73 | - Коллекция Dictionary [(Метанит)](https://metanit.com/sharp/tutorial/4.9.php) 74 | - Интерфейсы IEnumerable и IEnumerator [(Метанит)](https://metanit.com/sharp/tutorial/4.11.php) 75 | - Делегаты, лямбды 76 | - Делегаты [(Метанит)](https://metanit.com/sharp/tutorial/3.13.php) 77 | - События [(Метанит)](https://metanit.com/sharp/tutorial/3.14.php) 78 | - Анонимные методы [(Метанит)](https://metanit.com/sharp/tutorial/3.15.php) 79 | - Лямбды [(Метанит)](https://metanit.com/sharp/tutorial/3.16.php) 80 | - Делегаты Action, Predicate и Func [(Метанит)](https://metanit.com/sharp/tutorial/3.33.php) 81 | - Методы расширения [(Метанит)](https://metanit.com/sharp/tutorial/3.18.php) 82 | - LINQ 83 | - LINQ [(Метанит)](https://metanit.com/sharp/tutorial/15.1.php) 84 | - Фильтрация выборки и проекция [(Метанит)](https://metanit.com/sharp/tutorial/15.2.php) 85 | - Сортировка [(Метанит)](https://metanit.com/sharp/tutorial/15.3.php) 86 | - Работа с множествами [(Метанит)](https://metanit.com/sharp/tutorial/15.4.php) 87 | - Агрегатные операции [(Метанит)](https://metanit.com/sharp/tutorial/15.5.php) 88 | - Методы Skip и Take [(Метанит)](https://metanit.com/sharp/tutorial/15.11.php) 89 | - Группировка [(Метанит)](https://metanit.com/sharp/tutorial/15.6.php) 90 | - Методы All и Any [(Метанит)](https://metanit.com/sharp/tutorial/15.10.php) 91 | - Отложенное и немедленное выполнение LINQ [(Метанит)](https://metanit.com/sharp/tutorial/15.8.php) 92 | - Делегаты и анонимные методы в запросах LINQ [(Метанит)](https://metanit.com/sharp/tutorial/15.9.php) 93 | 94 | ## Exception, работа с исключениями (id-2.1) 95 | 96 | - [Обработка исключений](https://metanit.com/sharp/tutorial/2.14.php) 97 | - [Блок catch и фильтры исключений](https://metanit.com/sharp/tutorial/2.28.php) 98 | - [Типы исключений. Класс Exception](https://metanit.com/sharp/tutorial/2.29.php) 99 | - [Создание классов исключений](https://metanit.com/sharp/tutorial/3.17.php) 100 | - [Поиск блока catch при обработке исключений](https://metanit.com/sharp/tutorial/2.30.php) 101 | - [Генерация исключения и оператор throw](https://metanit.com/sharp/tutorial/2.31.php) 102 | 103 | # C# advanced 104 | 105 | ## OOD 106 | - [Паттерны от рефакторинг Гуру](https://refactoring.guru/ru) 107 | - [How to create better code using Domain-Driven Design](https://altkomsoftware.pl/en/blog/create-better-code-using-domain-driven-design/) 108 | - [Active Record](https://habr.com/ru/company/domclick/blog/515560/) 109 | - [DDD, Hexagonal, Onion, Clean, CQRS](https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/) 110 | - [CQRS + Event Sourcing](https://danielwhittaker.me/2020/02/20/cqrs-step-step-guide-flow-typical-application/) 111 | - [Using strongly-typed entity IDs to avoid primitive obsession](https://andrewlock.net/using-strongly-typed-entity-ids-to-avoid-primitive-obsession-part-1/) 112 | 113 | # Frameworks 114 | 115 | ## ASP Web API 116 | - [Create a web API with ASP.NET Core](https://docs.microsoft.com/en-us/learn/modules/build-web-api-net-core/) 117 | - [Build RESTFUL API witn ASP.NET Core](https://medium.com/free-code-camp/an-awesome-guide-on-how-to-build-restful-apis-with-asp-net-core-87b818123e28) 118 | - [DI](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection) 119 | - [Swagger](https://docs.microsoft.com/en-us/learn/modules/improve-api-developer-experience-with-swagger/) 120 | - [Logging](https://docs.microsoft.com/en-us/learn/modules/aspnet-logging/) 121 | - [EF](https://docs.microsoft.com/en-us/learn/modules/persist-data-ef-core/) 122 | - [Identity framework](https://docs.microsoft.com/en-us/learn/modules/secure-aspnet-core-identity/) 123 | - [Design Patterns: Asp.Net Core Web API, services, and repositories](https://www.forevolve.com/en/articles/2017/08/11/design-patterns-web-api-service-and-repository-part-1/) 124 | - [Five RESTFul Web Design Patterns Implemented](https://blog.jeremylikness.com/series/five-restful-web-design-patterns-implemented-in-asp.net-core-2.0) 125 | 126 | ## Blazor - Web UI 127 | - [Blazzor](https://docs.microsoft.com/en-us/learn/modules/build-blazor-webassembly-visual-studio-code/) 128 | 129 | ## Microservices 130 | - [Как работают микросервисы в контейнерах](https://dou.ua/lenta/articles/microservices-net-core/) 131 | 132 | ## WPF 133 | - [WPF](https://docs.microsoft.com/en-us/learn/modules/create-ui-for-windows-10-apps/) 134 | - [Reactive MVVM Pattern On The .NET Platform](https://worldbeater.medium.com/reactive-mvvm-for-net-platform-175dc69cfc82) 135 | 136 | ## .NET in deep 137 | -------------------------------------------------------------------------------- /Learn/Roadmap/roadmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Roadmap/roadmap.png -------------------------------------------------------------------------------- /Learn/Roadmap/roadmap.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kysect/Main/f8907949dfa1428c4a79d15b513e9d94554f1fba/Learn/Roadmap/roadmap.xmind -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kysect 2 | 3 | --- 4 | 5 | > Получай пользу принося пользу. 6 | 7 | --- 8 | 9 | Kysect - это комьюнити, которое сформировалось внутри университета из студентов, которые хотели вместе разрабатывать и учиться. Основным стеком является .NET и C#. В таком формате комьюнити существовало много лет, но после ухода из университета старый формат постепенно уходил в прошлое. Теперь на месте комьюнити остались лишь различные материалы и проекты, которые разрабатывались. Но мы всё ещё продолжаем эти проекты писать. Со список проектов можно ознакомиться в списке репозиториев, они все публичные. По организационным вопросам можно писать https://github.com/FrediKats. 10 | 11 | Полезные материалы: 12 | 13 | - [Roadmap знакомства с C#/.NET стеком](Learn/Roadmap/Roadmap.md) 14 | - [Немного про различную литературу](Learn/Books/Books.md). Обязательно дочитаем ещё много других книг и дополним! -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 578 | --------------------------------------------------------------------------------