.NET Разработчик
6.51K subscribers
427 photos
2 videos
14 files
2.04K links
Дневник сертифицированного .NET разработчика.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День восемьсот девяносто четвёртый. #Оффтоп
CUPID
Сегодня посоветую вам очередное видео с просторов Ютуба. В этом видео Дэниел Норт посягает на самое святое. Оказывается SOLID уже не торт!

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

Дэниел думал об этом очень давно, особенно с тех пор, как несколько лет назад он для развлечения «наехал» на принципы SOLID, и получил в ответ порцию хейта. Его пост о том, почему он считает, что SOLID устарел, оказался на первой странице Hacker News!

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

1. Composable (Интегрируемый)
Это значит, что модуль или библиотека легко встраивается в проект и может быть использована повторно. Код, который легко использовать повторно, используется повторно снова, и снова, и снова. Некоторые характеристики такого кода:
- Компактный интерфейс – требует меньше изучения, меньше возможностей использовать его неправильно, меньше конфликтов.
- Имя и описание чётко выражают намерение – такую библиотеку или NuGet-пакет легче найти и легче понять, что она делает.
- Имеет минимальное количество зависимостей.

2. Unix философия
Код делает одну вещь, но делает её хорошо. Примером послужили команды консоли в Unix. Например, ls, которая всего лишь выводит список файлов, но имеет огромное количество параметров и способов сортировки и обработки получаемого результата.
Кроме того, Unix философия подразумевает, что результат одной программы будет входными данными для другой и поощряет пайплайны.

3. Predictable (Предсказуемый)
Код делает то, что вы от него ожидаете. Всё равно, что «проходит все тесты», как говорят в TDD, но более обобщённо. Это также относится, например, к структуре проекта, где все вещи названы так и расположены там, где вы этого ожидаете, поэтому даже не знакомый с кодовой базой человек может быстро найти нужный кусок кода.

4. Idiomatic (Идиоматический)
Код легко понимается и использует характерные для языка или проекта конструкции, ключевые слова или выражения, стандарты кодирования и т.п. согласованно во всей кодовой базе.

5. Domain-based (Предметно-ориентированный)
Это означает не только использование в коде характерных для предметной области терминов, но и построение структуры проекта в соответствии с доменом, а не фреймворком.

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

Подробнее Дэниел рассказывает о CUPID в подкасте DotNet Rocks.

Что скажете?
👍2
День восемьсот девяносто пятый. #DesignPatterns #Microservices
Паттерны в Микросервисах
4. Saga
Если вы используете микросервисную архитектуру с базой данных на микросервис, то управление согласованностью с помощью распределённых транзакций является сложной задачей. Вы не можете использовать традиционный протокол двухфазной фиксации (2PC), поскольку он либо не масштабируется (базы данных SQL), либо не поддерживается (многие базы данных NoSQL).

Вы можете использовать паттерн Saga для распределённых транзакций в микросервисной архитектуре. Saga - это старый паттерн, разработанный в 1987 году как концептуальная альтернатива длительным транзакциям в базах данных SQL. Но современный вариант этого паттерна отлично работает и для распределённой транзакции. Паттерн Saga - это последовательность локальных транзакций, в которой каждая транзакция обновляет данные в хранилище данных в рамках одного микросервиса и публикует событие или сообщение. Первая транзакция в Saga инициируется внешним запросом (событием или действием). После завершения локальной транзакции (данные сохраняются в хранилище данных, а сообщение или событие публикуются) опубликованное сообщение/событие запускает следующую локальную транзакцию в Saga (см. картинку ниже).

Если локальная транзакция терпит неудачу, Saga выполняет серию компенсирующих транзакций, которые откатывают изменения предыдущих локальных транзакций.

В основном существует два варианта координации транзакций в Saga:
- Хореография: децентрализованная координация, при которой каждый микросервис производит и прослушивает события/сообщения других микросервисов и решает, следует ли предпринять действие или нет.
- Оркестрация: централизованная координация, при которой оркестратор сообщает участвующим микросервисам, какую локальную транзакцию необходимо выполнить.

Плюсы
- Обеспечение согласованности посредством транзакций в высокомасштабируемой или слабо связанной, управляемой событиями микросервисной архитектуре.
- Обеспечение согласованности посредством транзакций в микросервисной архитектуре, где используются базы данных NoSQL без поддержки 2PC.

Минусы
- Необходимо обрабатывать временные отказы и обеспечивать идемпотентность.
- Трудно отлаживать, и сложность растёт по мере увеличения количества микросервисов.

Когда использовать
- В высокомасштабируемой, слабо связанной микросервисной архитектуре, где используются источники событий https://t.iss.one/NetDeveloperDiary/1084.
- В системах, где используются распределённые базы данных NoSQL.

Когда не использовать
- Слабо масштабируемые транзакционные системы с базами данных SQL.
- В системах, где существует циклическая зависимость между сервисами.

Поддержка
Axon, Eventuate, Narayana

Подробнее
- Saga — распределённые транзакции
- Microservices Pattern: Saga

Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
👍2
День восемьсот девяносто шестой. #BestPractices
Лучшие Практики Использования RESTful API. Начало
Сегодня рассмотрим лучшие практики, которые можно использовать при работе с RESTful API.

1. Используйте JSON
В наши дни JSON является общепринятым стандартом для взаимодействия с API. Это предпочтительный выбор по сравнению с XML, поскольку он значительно снижает полезную нагрузку, что приводит к более быстрой передаче данных. Следовательно, ваши REST API должны использовать JSON для связи между клиентом и сервером. Обратите внимание, что REST не зависит от формата, что означает, что вы можете использовать любой формат для обмена данными, например XML, HTML, JSON и даже пользовательские форматы. Чтобы гарантировать, что ваш REST API обменивается данными в JSON, вы можете задать заголовок ответа Content-Type: application/json.

2. Версионирование
Версионирование - это процесс управления изменениями в API. Рекомендуется всегда добавлять версии в свой API. При разработке REST API следует помнить, что изменения неизбежны. Возможно, вам придётся внести критические изменения, чтобы удовлетворить потребности клиентов.
Такое критическое изменение может потребоваться из-за изменения формата данных ответа, изменения типа ответа, введения новых функций, редактирования или удаления существующих функций и т. д. Следовательно, крайне важно, чтобы у вас была стратегия реализации изменений.
Версионирование - одна из таких стратегий. Существуют разные варианты реализации версионирования API:
- URI
Это простейшая стратегия передачи информации о версии: поместить номер версии в путь URI. При этом по соглашению номер версии начинается с префикса «v»:
https://www.mywebsite.com/api/v1.0/products
https://www.mywebsite.com/api/v2.1/orders

- Параметр запроса
Вы можете указать информацию о версии в параметре запроса. При этом базовый URL останется прежним:
https://www.mywebsite.com/api/products/{id}?version=1.0
Это более гибкий подход к запросу версии ресурса.

- Заголовок запроса
Ещё один вариант - использовать заголовок Accept:
Accept: version=1.0
В этом случае вам не нужно вносить никаких изменений в URL-адрес.

3. Документация
API неполон без надлежащей документации. Документация должна быть общедоступной и содержать сведения о конечных точках API и циклах запроса/ответа. Помните, что после того, как ваш API станет общедоступным, вы не должны вносить изменений без уведомления.

4. Всегда используйте SSL
Всегда используйте SSL. Здесь вообще не может быть никаких исключений. К вашему API можно получить доступ практически из любого места, где есть подключение к Интернету. Следовательно, вы должны убедиться, что ваши API безопасны. Связь между сервером и клиентом, использующим ваш API, должна быть защищённой и зашифрованной.

Окончание следует…

Источник:
https://www.developer.com/web-services/best-practices-restful-api/
День восемьсот девяносто седьмой. #BestPractices
Лучшие Практики Использования RESTful API. Окончание
Начало

5. Аккуратно обрабатывайте ошибки
Вы должны аккуратно обрабатывать ошибки и возвращать соответствующие коды ответа HTTP, когда ошибка произошла. Коды ответа HTTP предоставят достаточно информации, чтобы понять причину ошибки и возникшую проблему.
Вот список распространённых кодов ответа HTTP:
- 400 Bad Request – неправильный запрос со стороны клиента
- 401 Unauthorized – неавторизованный клиент пытается получить доступ к ресурсу
- 403 Forbidden – клиент аутентифицирован, но не имеет прав для доступа к определённому ресурсу
- 404 Not Found – запрошенный ресурс не найден
- 415 Unsupported Media Type – клиент отправляет данные в формате, который не поддерживается сервером или для данного URI
- 422 Unprocessable Entity – клиент отправляет данные в понятном серверу формате, но сервер не может их обработать (например, отправлен неверный тип объекта)
- 500 Internal server error – сервер столкнулся с непредвиденными обстоятельствами, мешающими ему исполнить запрос
- 502 Bad Gateway – веб-сервер, к которому вы подключились, действует как прокси-сервер для ретрансляции информации с другого сервера, но получил неверный ответ от этого другого сервера
- 503 Service Unavailable – что-то неожиданное случилось на стороне сервера, и API недоступен.

Полезно возвращать подробные сведения об ошибке в теле ответа. Это поможет разработчикам выполнить отладку и обнаружить причину проблемы. Например:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Неверный запрос.",
"detail": {
"address": "Поле address является обязательным."
}
}

Следует последовательно использовать коды состояния. Например, если вы использовали 200 OK для конечной точки GET, вы должны использовать один и тот же код состояния для всех конечных точек GET. Вот примеры кодов ответа на разные типы запросов для обеспечения единообразия:
GET: 200 OK
POST: 201 Created
PUT: 200 OK
PATCH: 200 OK
DELETE: 204 No Content

6. Избегайте использования глаголов в URI
Вы не должны описывать выполняемое действие с помощью глаголов в URL-адресе. Использование глаголов в REST API - плохая практика. Сам метод HTTP - это глагол: GET, PUT, POST, DELETE, - а URL-адрес всегда должен содержать существительные. Из этого правила есть несколько исключений. Например, глаголы используются для некоторых конкретных действий:
/login
/logout
/register

7. Повышение производительности
- Про использование формата JSON вместо XML мы уже говорили выше.
- Используйте вызовы PATCH, когда объём данных, подлежащих обновлению, небольшой. В запросе PATCH обычно передаётся особый тип данных, говорящий серверу, какие поля объекта следует изменить, и как.
- Ограничьте количество полей, возвращаемых API. В большинстве случаев не требуется возвращать полное представление ресурса. Уменьшая количество полей, вы сможете минимизировать сетевой трафик и повысить производительность API.

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

Источник: https://www.developer.com/web-services/best-practices-restful-api/
👍1
День восемьсот девяносто восьмой. #DesignPatterns #Microservices
Паттерны в Микросервисах
5. Бэкенды для Фронтендов (BFF)
В современной разработке бизнес-приложений, особенно в микросервисной архитектуре, фронтенд и серверные приложения отделены друг от друга и представляют собой отдельные сервисы. Они общаются через API или GraphQL. Если в приложении также есть клиент для мобильного, использование одного и того же бэкенд микросервиса как для веб-клиента, так и для мобильного клиента становится проблематичным. Требования к API мобильного клиента обычно отличаются от требований веб-клиента, поскольку у них другой размер экрана, способ отображения, производительность, источник энергии и пропускная способность сети. См. картинку ниже.

Паттерн Бэкенды для Фронтендов можно использовать в сценариях, где каждый тип клиента получает отдельный серверный модуль, настроенный для конкретного пользовательского интерфейса. Паттерн также обеспечивает другие преимущества, например, выступает в качестве фасада для подчинённых микросервисов, тем самым уменьшая трафик между пользовательским интерфейсом и нижестоящими микросервисами. Кроме того, в сценарии с высокой степенью защиты, когда нижестоящие микросервисы развертываются в сети DMZ (демилитаризированной зоны), BFF используется для обеспечения более высокой безопасности.

Плюсы
- Разделение проблем между сервисами. Возможность оптимизировать их для конкретного пользовательского интерфейса.
- Обеспечение более высокого уровня безопасности.
- Снижение трафика между пользовательским интерфейсом и микросервисами нижестоящего уровня.

Минусы
- Дублирование кода между сервисами.
- Размножение сервисов в случае использования множества разных пользовательских интерфейсов (например, Smart TV, Web, Mobile, Desktop).
- Требуется тщательная разработка и реализация, поскольку BFF не должны содержать никакой бизнес-логики, только логику и поведение, специфичные для клиента.

Когда использовать
- Если приложение имеет несколько пользовательских интерфейсов с разными требованиями к API.
- Если требуется дополнительный уровень между пользовательским интерфейсом и микросервисами нижестоящего уровня по соображениям безопасности.
- Если при разработке пользовательского интерфейса используются микро-интерфейсы.

Когда не использовать
- Если у приложения несколько пользовательских интерфейсов, но они используют один и тот же API.
- Если основные микросервисы не развернуты в DMZ.

Поддержка
Большинство фреймворков для бэкенда (Node.js, Spring, Django, Laravel, Flask, Play, и т.д.).

Подробнее
- Бэкенды для фронтендов
- Microservices Pattern: API Gateway / Backends for Frontends

Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
👍3
День восемьсот девяносто девятый. #ЧтоНовенького
10 Советов по Повышению Продуктивности в Visual Studio 2019. Начало

В серии #ЧтоНовенького я много писал про новые функции в Visual Studio, но обычно это было про функции, которые только-только выходили в превью версиях. Поэтому сегодня небольшое саммари про инструменты, которые вы уже можете использовать в стабильной версии (16.10.3).

1. Умный перевод строки
Сочетание клавиш Shift+Enter после заголовка класса или метода, либо после названия блока (if, for, и т.п.) приведёт к тому, что Visual Studio автоматически поставит и выровняет фигурные скобки для блока, а также поместит курсор в начало пустой строки между скобками. Очень удобно.

2. Добавление недостающих директив using
Если вам нужно скопировать код и вставлять его в другой файл, иногда приходится тратить время на добавление директив using, которых нет в целевом файле. Чтобы не делать этого, зайдите в Options > Text Editor > C# > Advanced (Настройки > Текстовый редактор > C# > Дополнительно). Там в блоке Using Directives (Директивы Using) отметьте флажок «Add missing using directives on paste» (Добавлять недостающие директивы using при вставке).

3. Значок иерархии наследования
Если вы останетесь в том же окне настроек из пункта 2, и прокрутите до конца вниз, вы обнаружите ещё одну интересную функцию «Show inheritance margin» (Показывать поле наследования). Придётся перезагрузить студию, но это крутая штука. Для иерархий классов (а также для реализаций интерфейсов) слева от заголовков классов и методов будет показываться значок со стрелкой вверх или вниз, позволяющий быстро перейти к родительскому (стрелка вверх) или дочернему (стрелка вниз) классу или интерфейсу. Для родителей понятно, что можно найти имя класса в заголовке, а вот быстро вывести список всех наследников может быть очень полезно.

4. Убрать неиспользуемые ссылки
Это можно сделать из контекстного меню проекта «Remove Unused References» (Удалить Неиспользуемые Ссылки). Откроется диалоговое окно, где вы сможете просмотреть все ссылки на проекты, библиотеки или NuGet пакеты, которые не используются, и отметить те, которые вы хотите сохранить или удалить.

5. Графический интерфейс для .editorconfig
Файл .editorconfig позволяет вам обеспечить одинаковый стиль кодирования в ваших проектах. Особенно это полезно для командных проектов, где могут быть разные стандарты. Но раньше настраивать его было откровенно больно, т.к. это был просто текстовый файл. Теперь для него разработан GUI. В контекстном меню проекта или решения выберите Add > New EditorConfig (либо Add > New item… > editorconfig File). Откроется окно с сотнями настроек, которые можно задать через удобный графический интерфейс.

6. Очистка кода
Применить заданные в пункте 5 настройки в одно нажатие довольно легко с помощью функции Code Cleanup. Это маленький значок метлы в сроке состояния документа. Либо просто Ctrl+K, Ctrl+E. Параметры очистки кода также можно настроить.

Окончание следует…

Источник:
https://www.youtube.com/watch?v=b4T63cdGs0U
День девятисотый. #ЧтоНовенького
10 Советов по Повышению Продуктивности в Visual Studio 2019. Окончание
Начало

7. Добавление параметров в конструктор
Если встать курсором на определение свойства или поля класса, то меню быстрых действий (Ctrl+. или Alt+Enter) позволяет добавлять свойства класса в параметры конструктора (пункт меню «Add parameters to <имя конструктора>»). Кроме того, возможно добавить необязательный параметр, а если конструкторов несколько, будет предложено выбрать из них.
И наоборот, если встать курсором на параметр конструктора, в меню быстрых действий будут пункты «Create and assign …», позволяющие добавить и задать:
- свойство или поле с именем параметра, на котором стоит курсор,
- все недостающие свойства или поля из параметров конструктора.

8. Проверка параметров на null
Если встать курсором на параметр конструктора или метода, меню быстрых действий также может предложить добавить проверку на null («Add null check») для текущего параметра или для всех параметров ссылочных типов. При этом для строк есть возможность проверки на IsNullOrEmpty или IsNullOrWhiteSpace. По умолчанию для null генерируется выброс ArgumentException.

9. Конвертация в полное свойство
По умолчанию при генерации свойств используется сокращённый вариант автосвойства, например:
public string Name { get; set; }
Меню быстрых действий предлагает возможность преобразовать свойство в полный вариант с приватным полем (пункт меню «Convert to full property»), что выдаст примерно следующий код:
private string _name;
public string Name { get => _name;
set => _name = value; }
Можно пойти дальше, встать на get или set и выбрать из быстрых действий пункт «Use block body for accessors», что преобразует соответствующий аксессор в блочный вариант, например:
public string Name { get => _name; 
set
{
_name = value;
}
}
Аналогично возможно и обратное преобразование с помощью пункта меню «Use auto property».

10. Новый редактор Razor
В настройках среды Options > Environment > Preview Features (Настройки > Среда > Предварительный просмотр отметьте флажок «Enable experimental Razor editor» (Включить экспериментальный редактор Razor).
В новом редакторе Razor есть улучшенный механизм форматирования, который более консервативен, чем старый, а также намного умнее в том, как он обрабатывает ваш код. Некоторые быстрые действия теперь также доступны в файлах Razor:
- добавление директивы @using или полного имени типа,
- добавление проверки на null,
- переименование компонентов Blazor из тегов (файл компонента будет изменён автоматически),
- создание компонента Blazor из неизвестного тега,
- извлечение блока @code в файл отделённого кода,
- переход к определению компонента Blazor по F12.

Источник: https://www.youtube.com/watch?v=b4T63cdGs0U
День девятьсот первый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
91. Подробный Логгинг Нарушит Ваш Сон
Когда я встречаю систему, которая уже какое-то время находится в стадии разработки или производства, первым признаком реальных проблем всегда является грязный журнал. Вы знаете, о чем я говорю: когда в обычном режиме работы нажатие на одну ссылку на веб-странице приводит к шквалу сообщений в единственном журнале, который предоставляет система. Слишком подробный логгинг может быть столь же бесполезным, как и полное его отсутствие.

Если ваши системы похожи на мои, то, когда ваша работа сделана, чья-то чужая работа только начинается. Надеемся, что после того, как система будет разработана, она проживет долгую и благополучную жизнь, обслуживая клиентов (если вам повезёт). Как вам узнать, что что-то идёт не так, когда система находится в эксплуатации, и что в этом случае делать?

Может быть, кто-то следит за вашей системой за вас, а может вы будете следить за ней сами. В любом случае журналы, скорее всего, будут частью мониторинга. Если возникает проблема, и вас нужно разбудить среди ночи, чтобы решить её, вы должны быть уверены, что проблема действительно серьёзная. Если моя система умирает, я хочу знать об этом. Но если это просто мелкие косяки, я предпочитаю наслаждаться своим прекрасным сном.

Для многих систем первым признаком того, что что-то идёт не так, является запись сообщения в какой-либо журнал. Обычно это будет журнал ошибок. Так что сделайте себе одолжение: с первого дня разработки сделайте так, что, если уж что-то пишется в журнал ошибок, то вы готовы к тому, что кто-нибудь позвонит и разбудит вас по этому поводу посреди ночи. Если вы можете смоделировать нагрузку на свою систему во время тестирования, последующее отсутствие лишних записей в журнале ошибок является хорошим первым признаком того, что ваша система достаточно надёжна. В противном случае вы получите раннее предупреждение, что это не так.

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

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

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

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Johannes Brodwall
День девятьсот второй. #DesignPatterns #Microservices
Паттерны в Микросервисах
6. API-шлюз (API Gateway)
В архитектуре микросервисов пользовательский интерфейс обычно соединяется с несколькими микросервисами. Если микросервисы являются слишком узкоспециализированными (FaaS), клиенту может потребоваться подключение к большому количеству микросервисов, что становится сложным и требует множества различных коммуникаций. Кроме того, сервисы, включая их API, могут развиваться. Также крупные системы обычно добавляют стандартные задачи (SSL-терминацию, аутентификацию, авторизацию, троттлинг, ведение журнала и т. д.).

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

Достоинства
- Предлагает слабую связь между фронтендом и микросервисами на бэкенде.
- Уменьшает количество вызовов между клиентом и микросервисами.
- Повышает безопасность за счет централизованной SSL-терминации, аутентификации и авторизации.
- Централизованно управляет общими задачами, например, ведением журнала и мониторингом, троттлингом и балансировкой нагрузки.

Недостатки
- Сбой в API-шлюзе становится «единой точкой отказа» в микросервисной архитектуре.
- Увеличивает задержку из-за дополнительного сетевого вызова.
- Если не масштабировать API-шлюз, он легко может стать узким местом для всей системы.
- Увеличивает стоимость разработки и обслуживания.

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

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

Поддержка
Amazon API Gateway, Azure API Management, Ocelot, Apigee, Kong, WSO2 API Manager

Подробнее
- Использование API-шлюзов в микросервисах
- Microservices Pattern: API Gateway / Backends for Frontends

Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
👍2
День девятьсот третий.
8 Признаков Того, Что Вы не Контролируете Техническую Сложность
Обладая почти 25-летним опытом работы в качестве консультанта, я помогаю организациям, работающим в области .NET, повышать квалификацию в разработке программного обеспечения, от идеи до производства. Во время таких визитов я тщательно изучаю их методы разработки, стандарты качества, принципы проектирования, инструменты, которые они используют, их конвейер развёртывания, динамику команды, процесс выработки требований и многое другое.

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

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

2. Внедрение технологии, «потому что круто», потому что это помогает привлечь новый персонал, или просто потому, что руководство купилось на золотые горы, обещанные им разработчиками, поставщиками ПО или архитекторами.

3. Предоставление доступа к HTTP API или служебным конечным точкам другим командам или партнерам без контроля обязательств, которые необходимы в этом случае, например, чётко определённого управления версиями, обратной и прямой совместимости, надлежащей документации для разработчиков и т.п.

4. Команды, которые добавляют ненужную сложность, такую ​​как чрезмерное использование абстракций и дополнительных уровней, не обязательных в текущих требованиях. Часто это происходит под предлогом «подготовки к будущему» или для того, чтобы сделать систему «более тестируемой» (обычно это называют попыткой «замокать» всё на свете).

5. Архитекторы и технические руководители, которые любят хвастаться архитектурными принципами, шаблонами проектирования и универсальными эвристиками, необходимыми для «создания лучшего программного обеспечения», но в итоге насаждают свои догматические убеждения. Проблема не в том, что эти принципы плохие, а в том, что у архитекторов не хватает опыта, чтобы понять контекст, в котором эти принципы применяются, а также их плюсы и минусы.

6. Дисбаланс между тактической и стратегической архитектурой, с краткосрочными решениями на одном конце шкалы и чрезвычайно амбициозными (и нереалистичными) воздушными замками - на другом.

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

8. Разработчики, которые не могут найти способ совместной работы над одним и тем же фрагментом функциональности, потому что не знают, как объединить усилия или разбить работу на относительно независимые задачи.

С какими из описанных (или не описанных) здесь проблем сталкивались вы в своей карьере?

Источник: https://ddoomen.medium.com/8-signals-that-you-dont-control-your-technical-complexity-87ac4ae66975
Автор оригинала – Dennis Doomen
День девятьсот четвёртый. #BestPractices
Лучшие Практики Написания Комментариев к Коду. Начало
Знаменитый профессор MIT Хэл Абельсон сказал: «Программы должны писаться для того, чтобы быть прочитанными людьми и лишь на всякий случай - для выполнения машинами». Хотя он, возможно, намеренно недооценил важность исполнения кода, он чётко понимает, что у программ есть две очень разные аудитории. Компиляторы и интерпретаторы игнорируют комментарии и считают, что все синтаксически правильные программы одинаково просты для понимания. Читатели-люди сильно от них отличаются. Нам кажется, что одни программы труднее понять, чем другие, и мы ищем комментарии, которые помогут нам разобраться в них.

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

1. Комментарии не должны дублировать код
Многие начинающие программисты пишут слишком много комментариев, потому что их научили этому в школе. Кого-то учили добавлять комментарий к каждой закрытой скобке, чтобы указать, какой блок заканчивается:
if (x > 3) {

} // if
Некоторые преподаватели требовали от студентов комментировать каждую строчку кода. Хотя это может быть разумной политикой для совсем уж новичков, но такие комментарии похожи на ходунки для младенцев, и их следует удалять, как только вы научились ходить.

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

Канонический плохой пример:
i = i + 1; // Добавляем 1 к i
Комментарий не несёт никакой информации, но повышает стоимость поддержки кода.

2. Хорошие комментарии не оправдывают непонятный код.
Ещё одно неправильное использование комментариев - предоставление информации, которая должна быть в коде. Простой пример - когда кто-то называет переменную одной буквой, а затем добавляет комментарий, описывающий ее назначение:
private static Node getBestChildNode(Node node) {
Node n; //кандидат на лучшего потомка
foreach (Node node in node.getChildren()) {
//обновляем n, если текущий лучше
if (n == null || utility(node) > utility(n))
n = node;
}
return n;
}

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

Node bestNode;
foreach (Node currentNode in node.getChildren()) {

}
Не комментируйте плохой код, просто перепишите его.

Продолжение следует…

Источник:
https://stackoverflow.blog/2021/07/05/best-practices-for-writing-code-comments/
День девятьсот пятый. #BestPractices
Лучшие Практики Написания Комментариев к Коду. Продолжение
Начало

3. Если вы не можете написать чёткий комментарий, возможно, проблема в коде
Самый печально известный комментарий в исходном коде Unix: «Никто не ожидает, что вы это поймёте», - располагался перед каким-то непонятным кодом переключения контекста. Позже Деннис Ричи объяснил, что это было написано в смысле "Этого не будет на экзамене", а не чтобы потроллить читателей. К сожалению, выяснилось, что ни он, ни соавтор Кен Томпсон сами не понимали этого кода и позже пришлось его переписать.

Это напоминает закон Кернигана: «Отладка в два раза сложнее, чем изначальное написание кода. Следовательно, если вы напишете код настолько умно, насколько это возможно, вы по определению недостаточно умны, чтобы отлаживать его.»

Предупреждать читателей, что они могут не понять ваш код, всё равно что включить аварийку в машине: признаться, что вы знаете, что нарушаете ПДД. Вместо этого перепишите код так, чтобы вы понимали его достаточно хорошо, чтобы объяснить кому-то, или, ещё лучше, чтобы объяснения не требовалось.

4. Комментарии должны прояснять ситуацию, а не запутывать
Обсуждение плохих комментариев было бы неполным без этой истории из книги Стивена Леви «Хакеры: герои компьютерной революции»:
[Питер Сэмсон] отличался тем, что отказывался добавлять поясняющие комментарии к своему исходному коду. Одна хорошо распространённая программа, написанная Сэмсоном, содержала сотни инструкций на языке ассемблера, с одним комментарием рядом с инструкцией, содержащей число 1750. Комментарий был: «RIPJSB», - и люди ломали голову над его значением, пока кто-то не понял, что 1750 - это был год смерти Баха, и что Сэмсон написал аббревиатуру для «Покойся с миром Иоганн Себастьяна Баха».

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

5. Поясняйте нестандартный код в комментариях
Рекомендуется комментировать код, который кто-то может счесть ненужным или избыточным, например этот код из App Inventor:
final Object value = (new JSONTokener(jsonString)).nextValue();
// Note that JSONTokener.nextValue() may return
// a value equals() to null.
if (value == null || value.equals(null)) {
return null;
}
Без этого комментария кто-то может «упростить» код или рассматривать его как загадочное, но важное заклинание. Сэкономьте время и беспокойство будущих читателей, написав, зачем нужен код.

Необходимо принять решение относительно того, требует ли код пояснения. Например, в учебнике по Kotlin есть такой код:
if (b == true)
Странно, почему бы не использовать просто
if (b)
, как это было бы в Java или C# (да и куче других языков). Однако, оказывается, что обнуляемые булевы переменные в Kotlin специально явно сравниваются с true, чтобы избежать уродливой проверки на null:
if (b != null && b)

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

Продолжение следует…

Источник:
https://stackoverflow.blog/2021/07/05/best-practices-for-writing-code-comments/
День девятьсот шестой. #BestPractices
Лучшие Практики Написания Комментариев к Коду. Продолжение
Начало
Продолжение

6. Предоставляйте ссылки на источник скопированного кода
Если вы такой же, как и большинство программистов, вы «иногда» используете код, который находите в Интернете. Добавление ссылки на источник позволяет будущим читателям получить полный контекст, например:
- какая проблема решалась,
- кто предоставил код,
- почему рекомендовано это решение,
- что об этом думают комментаторы,
- работает ли это решение до сих пор,
- как его можно улучшить.

Например, рассмотрим этот комментарий:
/* Преобразует Drawable в Bitmap. 
См. https://stackoverflow.com/a/46018816/2219998 */

Переход по ссылке на ответ показывает:
- Автор кода - Tomáš Procházka, который входит в топ 3% контрибьюторов на Stack Overflow.
- Один комментатор предлагает оптимизацию, уже включенную в репозиторий.
- Другой комментатор предлагает способ избежать крайнего случая.

Сравните это с этим комментарием (слегка изменённым для защиты авторов):
// Магическая формула, взятая со stackoverflow.
// По общему мнению, основана на человеческом восприятии.
return (int) (0.3 * red + 0.59 * green + 0.11 * blue);

Любому, кто захочет понять этот код, придётся искать формулу. Вставить URL-адрес намного быстрее, чем искать ссылку позже.

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

Люди копируют много кода из вопросов и ответов на Stack Overflow. Этот код подпадает под действие лицензий Creative Commons, требующей указания авторства. Комментарий со ссылкой удовлетворяет этому требованию.

Точно так же вы можете ссылаться на полезные учебные пособия, чтобы их можно было найти снова, а также в виде благодарности их автору:
// Большое спасибо Chris Veness за отличные примеры:
// https://www.movable-type.co.uk/scripts/latlong.html

7. Добавляйте ссылки на внешние источники, где они будут наиболее полезны
Например:
/* На https://tools.ietf.org/html/rfc4180 
советуют завершать строки в CSV файле символом CRLF
поэтому используем \r\n */
csvStringBuilder.append("\r\n");
Ссылки на стандарты и другую документацию могут помочь читателям понять проблему, которую решает ваш код. Хотя эта информация может быть где-то в проектном документе, комментарий в правильном месте даст читателям информацию там, где она больше всего нужна. В этом случае переход по ссылке даст полезную информацию о том, что стандарт RFC 4180 был обновлен до RFC 7111.

Окончание следует…

Источник:
https://stackoverflow.blog/2021/07/05/best-practices-for-writing-code-comments/
День девятьсот седьмой. #BestPractices
Лучшие Практики Написания Комментариев к Коду. Окончание
Начало
Продолжение 1
Продолжение 2

8. Добавляйте комментарии при исправлении ошибок
Комментарии следует добавлять не только при первоначальном написании кода, но и при его изменении, особенно при исправлении ошибок. Обратите внимание на этот комментарий:
/* ПРИМЕЧАНИЕ: как минимум, в Firefox 2, если пользователь уводит курсор за пределы окна браузера, событие перемещения мыши (и даже отпускания мыши) не будет получено, пока пользователь не перетащит курсор обратно в окно. Обойти проблему можно, реализовав onMouseLeave(). */
public void onMouseMove(Widget sender, int x, int y) { … }

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

Также может быть полезно сослаться на проблему в багтрекере:
// Имя используется в качестве заголовка, 
// если свойство заголовка не задано (баг #1425).

Если в системе контроля версий вы чётко следите за сообщениями коммитов, и добавляете в них ссылки на проблемы багтрекера, git blame можно использовать для поиска коммита, в котором было изменение. Хотя здесь могут быть варианты. Если исправление состояло из нескольких коммитов или были более серьёзные изменения, вроде перемещения метода в другой класс или переименования/перемещения файлов, тогда поиск источника исправления может сильно усложниться.

9. Используйте комментарии, чтобы отмечать незавершённые реализации
Иногда необходимо внести код в систему контроля версий, даже если он не завершён. Хотя может возникнуть соблазн не сообщать об известных недостатках в коде, лучше сделать их явными, например, с помощью комментария TODO:
/* TODO(hal): мы используем десятичный разделитель точку, вне зависимости от региона пользователя. Нам нужно подумать о том, как разрешить запятую в качестве десятичного разделителя, что потребует обновления синтаксического анализа чисел и других мест, где числа парсятся из строк, таких как FormatAsDecimal */

Использование стандартного формата для таких комментариев помогает измерить и устранить технический долг. А ещё лучше добавить проблему в багтрекер и указать ссылку на неё в своём комментарии.

Итого
Я надеюсь, что приведённые выше примеры показали, что комментарии не извиняют и не исправляют плохой код; они дополняют хороший код, предоставляя информацию другого типа. Как писал соучредитель Stack Overflow Джефф Этвуд: «Код говорит вам, как, а комментарии говорят вам, почему».
Следование этим правилам поможет вам и вашим товарищам по команде сэкономить время и нервы. Тем не менее, я уверен, что эти правила не являются исчерпывающими, и с нетерпением жду ваших вариантов в комментариях.

Источник: https://stackoverflow.blog/2021/07/05/best-practices-for-writing-code-comments/
День девятьсот восьмой. #DesignPatterns #Microservices
Паттерны в Микросервисах
7. Душитель (Strangler)
Если мы хотим использовать микросервисную архитектуру в унаследованном проекте, нам необходимо перенести устаревшие или существующие монолитные приложения на микросервисы. Перемещение существующих и работающих крупных монолитных приложений на микросервисы является довольно сложной задачей, так как это может нарушить доступность приложения.

Одно из решений - использовать паттерн Душитель. Он предполагает постепенную миграцию монолитного приложения на микросервисную архитектуру путём постепенной замены определённых функций новыми микросервисами. Кроме того, новый функционал добавляется только в микросервисы, минуя устаревшее монолитное приложение. Затем настраивается фасад (API-шлюз https://t.iss.one/NetDeveloperDiary/1106) для маршрутизации запросов между устаревшим монолитом и микросервисами. После того, как функциональность перенесена на микросервисы, фасад перехватывает клиентский запрос и направляет его на новые микросервисы. После переноса всего функционала старого монолита получается, что монолитное приложение «задушено», то есть оно выводится из эксплуатации. См. картинку ниже.

Достоинства
- Безопасная миграция монолитного приложения на микросервисы.
- Миграция и разработка нового функционала могут идти параллельно.
- Процесс миграции может иметь свой темп, весь функционал постоянно доступен клиентам.

Недостатки
- Совместное использование хранилища данных между существующим монолитным приложением и новыми микросервисами становится сложной задачей.
- Добавление фасада (API-шлюза) увеличит время отклика системы.
- Сквозное тестирование становится трудным.

Когда использовать
- Постепенная миграция большого серверного монолитного приложения на микросервисы.

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

Поддержка
Бэкенд фреймворки с поддержкой API-шлюзов.

Подробнее
- Паттерн Душитель
- Microservices Pattern: Strangler application

Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
👍1
День девятьсот девятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
92. Когда Программисты и Тестировщики Сотрудничают
Когда тестировщики и программисты начинают сотрудничать, случается магия. Меньше времени тратится на отправку ошибок туда-сюда через багтрекер. Меньше времени тратится на попытки выяснить, действительно ли что-то является ошибкой или новой функцией, и больше времени тратится на разработку хорошего программного обеспечения, отвечающего ожиданиям клиентов. Есть много возможностей начать сотрудничать ещё до того, как начнётся кодирование.

Тестировщики могут помочь клиентам писать и автоматизировать приёмочные тесты, используя язык их предметной области, с помощью инструментов вроде SpecFlow. Когда эти тесты передаются программистам до начала кодирования, команда практикует разработку, основанную на приёмочных тестах (ATDD). Программисты пишут основу для запуска тестов, а затем код, чтобы тесты проходили. Затем эти тесты становятся частью набора регрессионных тестов. Когда происходит такое сотрудничество, функциональные тесты завершаются раньше, что даёт время для исследовательского тестирования пограничных условий или более широкого тестирования рабочих процессов.

Мы можем сделать ещё один шаг вперед. Как тестировщик, я могу представить большинство своих идей по тестированию до того, как программисты начнут кодировать новый функционал. Когда я спрашиваю программистов, есть ли у них какие-либо предложения, они почти всегда предоставляют информацию, которая помогает мне лучше покрыть код тестами или не тратить много времени на ненужные тесты. Часто мы предотвращаем дефекты, потому что тесты проясняют многие из первоначальных идей. Например, в одном проекте, над которым я работала, тесты, которые я дала программистам, отображали ожидаемые результаты запроса в ответ на поиск по шаблону. Программист же твёрдо намеревался реализовать поиск только по полным словам. Мы смогли поговорить с заказчиком и определить правильные требования до начала кодирования. Сотрудничая, мы предотвратили дефект, что сэкономило нам обоим много времени.

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

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

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Janet Gregory
День девятьсот десятый. #ВопросыНаСобеседовании
Сегодня порекомендую вам не видео, а серию подкаста DotNet & More про вопросы на собеседовании. Серия вышла ещё в конце мая, но вот наткнулся на неё только сейчас. Ребята 2,5 часа обсуждают, что их спрашивали на собеседованиях, и что они стараются спрашивать, когда находятся по другую сторону стола.

Вообще, обсуждение довольно интересное. Поэтому, если у вас есть свободное время по пути на работу (или в отпуск), слушайте.

Выпуск доступен на YouTube или звуком на Anchor.