29 заметок с тегом

программирование

Идеи для программистов

Много начинающих программистов — сам был таким — маются от вопроса: чего бы такого классного напрограммировать. Месяц за месяцем, год за годом проходят в ожидании достойной идеи™. «Вот бы мне проект, я уж я бы взялся за него, я б тогда выложился на все сто».

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

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

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

Смысл не в том, чтобы сделать продукт. И даже не в том, чтобы выключить радары, в поисках крутую идею. Смысл в том, чтобы, пока крутая идея не пришла, занять время чем-то полезным. А потом, когда придёт время клёвого проекта, скилл уже будет прокачан и будет шанс не запороть идею, а таки реализовать её.

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

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

Оригинал статьи: https://t.me/anatoly_burov_channel/116 

 Нет комментариев    638   24 дн   программирование

stateless и stateful сервисы

Пример stateful системы
Например наша система хранит в себе сессии пользователей, тем самым ответ на запрос пользователя зависит от состояния (сессии). При масштабировании сервиса, нам прийдется переносить все сессии на новый инстанс. Система стает сложной и не маневренной. Любой stateful сервис можно превратить в stateless, вынеся состояние в отдельный сервис и БД. Так мы можем вынести сессии во внешнее хранилище, сама система осталась stateful, но сам веб сервис stateless, тем самым мы можем просто его реплицировать.

Пример stateless системы
Давайте вместо сессий использовать cookie файлы, таким образом мы передаем серверу не только сам запрос, но и всю необходимую информацию для его выполнения. Серверу больше не надо хранить в себе состояние. Stateless система зависит только от данных которые ей были переданы, а не от внутреннего состояния.

Еще один пример
У нас есть интернет магазин — пока корзина пользователя хранится в памяти сервера, то это stateful. И у нас сразу возникают проблемы с масштабированием. Но когда мы выносим хранения корзины во внешний session storage — наш сервис становится stateless и мы можем спокойно его масштабировать, так как состояние хранится у нас в отдельном хранилище.

Очень советую почитать статью на RSND по данной теме.

 Нет комментариев    189   1 мес   программирование

Как я делал бота для Facebook workplace

Дали мне задачу: написать бота для мессенджера workplace, с помощью которого можно получать уведомления из нашей CRM и управлять разными вещами. Расскажу о разных интересных вещах с которыми я столкнулся. Бота писал с помощью ASP.NET Core Web API.

Вебхуки

Для того чтобы бот мог обрабатывать запросы и сообщения от Facebook нам надо настроить вебхуки. Webhook — механизм оповещения системы о событиях. Для того чтобы Facebook принял наш хук, он должен обрабатывать как GET так и POST запросы.

Подробнее о Webhook в официальной документации

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

Показать код метода-обработчика GET запроса

public IActionResult Receive(
[FromQuery(Name = "hub.mode")] string mode,

    [FromQuery(Name = "hub.challenge")] string challenge,

    [FromQuery(Name = "hub.verify_token")] string verifyToken)
{

   if (string.IsNullOrEmpty(verifyToken)) {

       return Unauthorized();

    }


    if (verifyToken.Equals(FacebookEnvironment.FacebookVToken)) {

        return Ok(challenge);

    }

    return Unauthorized();

}

В качестве verify_token используется токен, который мы указали при регистрации нашего хука.

Показать код метода-обработчика POST запроса

public async Task<IActionResult> Receive([FromBody]FbResponse response = null)
{
    if (response is null) {
        return BadRequest();
    }

    if (response.Object != "page") {
        return Ok();
    }

    foreach (var entry in response.Entries) {
        foreach (var message in entry.Messaging) {
            await PrepareMessageAsync(message);
        }
    }
    return Ok("EVENT_RECEIVED");
}

Авторизация запросов Facebook

Для авторизации Facebook использует специальный http заголовок (X-Hub-Signature), в нем он передает некую сигнатуру с помощью которой мы можем авторизовать запрос. Для того чтобы добавить такую функциональность в наш контроллер, добавим фильтр.

Пример кода, для проверки подписи

private const string Sha1Prefix = "sha1=";

public static bool Validate(string signature, string contentString) {
    if (!signature.StartsWith(Sha1Prefix, StringComparison.OrdinalIgnoreCase)) {
        return false;
    }
    var secret = Encoding.ASCII.GetBytes(FacebookEnvironment.AppSecret);
    var signatureWithoutPrefix = signature.Substring(Sha1Prefix.Length);
    var content = Encoding.ASCII.GetBytes(contentString);
    return GetIsHashValid(secret, signatureWithoutPrefix, content);
}

private static bool GetIsHashValid(byte[] secret, string signature, byte[] content) {
    using var hmac = new HMACSHA1(secret);
    var hash = hmac.ComputeHash(content);
    var hashString = ToHexString(hash);
    return hashString.Equals(signature);
}

private static string ToHexString(IReadOnlyCollection<byte> bytes)
{
    var builder = new StringBuilder(bytes.Count * 2);
    foreach (var b in bytes)
    {
        builder.AppendFormat("{0:x2}", b);
    }

    return builder.ToString();
}

Тестирование бота

Как установить letsencrypt сертификат для IIS. Если же вы используете связку в виде ubuntu и nginx вам подойдет эта инструкция.

Для тестирования нужно развернуть бот на сервере, который смотрит в мир. Также необходимо чтобы у сервера было доменное имя и валидный SSL сертификат. В моем случае, в качестве сервера выступала машина на винде, так как другой внутри нашей сети не было. Как мне показалось захостить приложение написанное на .NET Core намного проще под Ubuntu + nginx нежели под Windows + IIS. В качестве поставщика сертификатов выбрал letsencrypt, так как они предоставляют бесплатный сертификат на 3 месяца, с возможностью дальнейшего обновления.

 Нет комментариев    180   1 мес   asp.net core   программирование

Удаления дубликатов строк

Недавно мне попалась интересная задачка по SQL.
У вас есть таблица с 2 колонками: Id, Name. Но на колонках нет никаких ограничений. И получилось так что там если дубли и нам надо их удалить.

Пример таблички

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

; WITH DuplicatesForDelete(Row) AS (
	SELECT ROW_NUMBER() OVER(PARTITION BY t1.Id, t1.Name ORDER BY Id, Name) AS Row 
	FROM TableWithDuplicates t1
)
DELETE FROM DuplicatesForDelete WHERE Row > 1

Статья о том что такое оконные функции (OVER) 

 Нет комментариев    430   2 мес   sql   программирование

Parallel, Asynchronous, Multithreading programming

Многопоточное программирование

Код может выполнятся в разных потоках. Например основной UI поток и набор потоков для обработки данных. В данном случае нет гарантии что потоки будут работать параллельно. Обычно это зависит от процессора. Потоки «абстрагируют» от пользователя низкоуровневые детали и позволяют выполнять более чем одну работу «параллельно».

Параллельное программирование

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

IEnumerable<Data> yourData = GetYourData();
var result = yourData.AsParallel() // начинаем обрабатывать параллельно
  .Select(d => d.CalcAmount()) // Вычисляем параллельно
  .Where(amount => amount > 0)
  .ToArray(); // Возврвщаемся к синхронной модели

Асинхронное программирование

Мы запускаем какую-то задачу, но не ждем ответа, а продолжаем делать свою работу. А когда будет готов ответ — нас уведомят. Обычно такие операции бывают при работе с сетью, диском или любыми другими продолжительными задачами.

Пример на C#.
У нас есть продолжительная асинхронная задача, которая обращается к БД. С помощью конструкций async/await мы организовываем асинхронную работу. Пока БД готовит для нас ответ, поток, который обслуживал этот метод возвращается в пулл потоков и может тем временем выполнять полезную работу. Как только БД отдаст ответ, нашему методу снова выделяется поток и продолжается работа.

var asyncResult = await Database.GetAllUsers(); // длительная асинхронная операция
var activeUsers = asyncResult.Where(user => user.IsActive).ToList(); // работаем с результатом асинхронной операции

Еще один забавный но наглядный пример

Вам нужно выкопать во дворе бассейн.

  1. Вы взяли лопату и копаете. Это однопоточная работа
  2. Вы пригласили друга Васю и копаете вместе, периодически задевая друг-друга лопатами. Это многопоточная работа
  3. Пока вы копаете бассейн, Вася копает канаву под водопровод. Никто никому не мешает. Это распараллеливание
  4. Вы пригласили бригаду землекопов, а сами с Васей пошли пить пиво. Когда бригада все сделает, к вам придут за деньгами. Это асинхронная работа.

Количество лопат в хозяйстве — это количество ядер в системе

Ссылки

Параллелизм против многопоточности против асинхронного программирования: разъяснение
Cтатья об async/await в C#
Многопоточное vs асинхронное программирование (stackoverflow) 

 Нет комментариев    104   2 мес   .net   программирование
 Нет комментариев    387   2 мес   c#   программирование

Лучшее объяснения работы семафора

A semaphore is like a nightclub: it has a certain capacity, enforced by a bouncer. Once it’s full, no more people can enter, and a queue builds up outside. Then, for each person that leaves, one person enters from the head of the queue. The constructor requires a minimum of two arguments: the number of places currently available in the nightclub and the club’s total capacity.

 Нет комментариев    79   3 мес   .net   c#   программирование

Небольшая заметка об индексах в ms sql

Индексы это важная часть большинства серверов баз данных. Они позволяют ускорить доступ к данным. Суть индексов хорошо описывает следующий пример: оглавление книги, оно позволяет найти нужную нам страницу вместо перебора всех страниц. Но у индексов есть недостатки: они заполняют дополнительное место (бывают случаи что индексы занимают в 3 раза больше места чем сами данные), также замедляются операции изменения данных, так как теперь нам надо менять еще и индексы.

Что из себя представляет индекс?

Внутри сервера они представлены в виде B-tree, где B означает сбалансированное, а не бинарное дерево.

Например мы хотим найти запись с Id = 2581.
Начиная с корня, выполняется поиск наименьшего значения ключа, большего или равного требуемому. Так мы найдем узел 18316, потом спустимся в узел 9031 и там мы увидим что есть прямая ссылка на лежащие данные по ключу 2581, после чего осуществляем вычитку данных.

Кластерный индекс

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

Не кластерный индекс

Структура такая же как и кластерного индекса, но с двумя отличиями:

  1. Не изменяет физическое упорядочивание данных.
  2. Страницы индекса состоят из ключа индекса и ссылки на строку.

SQL Server использует индекс для нахождения записей, совпадающих с условиями запроса.

Составной ключ в индексе

SQL Server позволяет создавать индексы по нескольким колонкам. Но в таком случае у нас появляется ограничение. Длинна составного ключа не должна быть больше 900 байт. Но бывают исключения, например у нас есть две колонки, каждая из которых длинной в 500 байт. Сервер создаст индекс, в случае если нет данных, которые будут превышать длину в 900 байт.

Также стоит помнить что индексы типа (Col1, Col2) и (Col2, Col1) разные.

Уникальные индексы

Такие индексы создаются для реализации целостности данных. Таким образом сервер гарантирует уникальные значение для указанной колонки или составного ключа.

Статьи, которые советую почитать чтобы глубже разобраться в теме

  1. Очень хорошая статья о всех типах индексов, когда их стоит создавать и как использовать
  2. Индексы. Теоретические основы.
 Нет комментариев    92   4 мес   sql   программирование   структуры данных

Изучение SQL: рекурсивные запросы

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

Общий вид рекурсивного запроса

WITH <имя> (<список столбцов>)
AS (
	SELECT    -- анкорная часть
	UNION ALL -- рекурсивная часть
        SELECT FROM <имя>
        WHERE <условие продолжения интерации>
)

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

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

Наполнение таблицы.

Код запроса:

;WITH OrgStructure AS 
(
	SELECT Id, ParentId, EmployeeType, EmployeeName
	FROM Employees
	WHERE EmployeeName = 'Jim' -- отправная точка, нам надо найти менеджера сотрудника Jim

	UNION ALL

	SELECT e.Id, e.ParentId, e.EmployeeType, e.EmployeeName
	FROM Employees as e
	JOIN OrgStructure as os
	ON e.Id = os.ParentId
)

SELECT * FROM OrgStructure
WHERE EmployeeType = 'manager' -- указываем что мы ищем менеджера.

Пример 2
Найдем первые 10 чисел Фибоначчи:

;WITH FIBONACHI AS 
(
	SELECT
		1 Iteration,
		1 SecondValue,
		2 CurrentValue
	UNION ALL

	SELECT
		Iteration + 1,
		SecondValue = CurrentValue,
		CurrentValue = SecondValue + CurrentValue
	FROM FIBONACHI
	WHERE Iteration < 10
)
SELECT CurrentValue FROM FIBONACHI
 Нет комментариев    73   4 мес   sql   программирование
Ранее Ctrl + ↓