Статья DevCrm 00: «Как мы делали CRM на WPF: от идеи до прототипа»
Вступление
Я уже делал CRM раньше. На учебном проекте. В группе. Быстро, наспех, чтобы сдать и забыть. И каждый раз, когда я открывал тот код, меня передёргивало. Там не было структуры. Там был хаос. Файлы лежали где попало, логика перемешивалась с интерфейсом, а имена переменных не имели смысла.
Я смотрел на этот код и чувствовал неудовлетворённость. Не от того, что «сделал плохо», а от того, что не довёл до конца. Что оставил это висеть. Как незакрытый гештальт, который не давал покоя.
Именно тогда, на том учебном проекте, родилась мысль: сделать свою CRM. С нуля. Не спеша. С чистым кодом, понятной структурой, красивым интерфейсом и хорошим чувством внутри. Чтобы самому было приятно открыть её через месяц, год, пять лет — и не стыдно.
И когда через несколько лет я сел за разработку, я не просто писал код. Я закрывал тот самый гештальт. И каждый кусок кода, каждая строчка, каждая вкладка — всё это было не просто работой. Это было возвращением к тому, что я оставил незавершённым.
Почему WPF?
Я даже не знаю, почему я выбрал именно его. Если смотреть историческую справку, всё начиналось с локальных окон. Каждый писал своё окно как хотел — тогда это было просто. Никаких серверов, никаких протоколов. Ты открываешь IDE, создаёшь форму, кидаешь кнопку — и она работает.
А потом появился Интернет. И все побежали делать веб. Серверы, клиенты, запросы, ответы. Это было удобно для обмена данными, но в этом потерялась та самая простота. Теперь, чтобы сделать одну маленькую кнопку, нужно поднять целую инфраструктуру.
И вот меня потянуло по этой исторической справке сделать "своё окно". Без веба. Без сервера. Без всего этого слоя, который висит между тобой и пользователем. Просто приложение, которое запускается на компьютере и делает своё дело. Как в старые добрые времена.
Это было моё начало. Так я и выбрал WPF.
MVVM
MVVM пришёл позже. Сначала я просто писал код в MainWindow.xaml.cs, как в старых добрых WinForms. Но когда кода стало больше ста строк, я понял: так не пойдёт. Логика перемешивается с интерфейсом, и разбираться в этом через месяц будет невозможно. Тогда я вспомнил про MVVM — и начал переписывать. Медленно, слой за слоем: модели, репозитории, сервисы, вьюмодели.
Это было не просто «применение паттерна». Это было осознанное решение — разделить ответственность, чтобы код не превратился в кашу. И это оказалось правильным решением.
По сути, любой инженер, даже самый маленький, ведёт свою деятельность «паттерновски». Потому что паттерны — это не выдумка архитекторов. Это способ мышления, который мы впитываем с опытом: разделять, структурировать, не смешивать.
Просто в программировании эти паттерны имеют названия и чёткие правила. Но сам подход — он везде. В чертежах, в процессах, в организации рабочего места. И MVVM для меня оказался не чем-то новым, а просто проекцией моего привычного способа работы на код.
Поэтому, когда я начал собирать проект, я не «применял паттерн». Я просто продолжал делать то, что всегда делаю: класть вещи по своим местам. Модели — отдельно. Логику — отдельно. Интерфейс — отдельно. И это сработало сразу.
Первая модель
Когда структура начала вырисовываться, встал следующий вопрос: с чего начинать писать код?
Я просто начал с модели Client. Потому что в CRM главное — клиент. Всё остальное строится вокруг него: задачи, заметки, взаимодействия, пользователи. Если я правильно опишу клиента, всё остальное приложится.
csharp public class Client { public int Id { get; set; } public string Name { get; set; } public string Phone { get; set; } public string Email { get; set; } public string Status { get; set; } // … и так далее } Просто. Понятно. Без лишней магии.
Потом добавились User, Task, Note, Interaction. Каждая модель появлялась не по плану, а по необходимости. Нужно было привязать клиента к пользователю — появился AssignedUserId. Нужно было добавить заметки — появилась модель Note. Всё это естественно вытекало из логики, а не из заранее нарисованной схемы.
Хранилище
Когда модели были готовы, встал вопрос: где всё это хранить?
Можно было сразу пойти в реляционную базу. Но я решил начать с простого: встроенная SQLite. Никаких установок, никаких серверов. Просто файл, который лежит рядом с приложением. Как в старые времена.
Это было осознанное решение: сначала сделать так, чтобы работало. А потом, если понадобится, добавить другие базы. И этот подход себя оправдал.
Первые данные
База появилась. Но данные в ней были пустые. А тестировать на пустой базе — это как пробовать новую машину на холостых оборотах. Всё работает, но непонятно, как оно поведёт себя в движении.
Я добавил тестовые данные прямо в контекст. Не через миграции, а через EnsureCreated() и EnsureSeedData(). Тогда это казалось временным решением. На самом деле оно осталось и работает до сих пор.
Интерфейс
Когда база заработала, я перешёл к главному: интерфейсу.
Я не стал проектировать идеальный UI. Просто взял стандартный DataGrid, привязал список клиентов, добавил пару кнопок — «Добавить», «Сохранить», «Удалить». Всё это работало через команды, и это было первое, что я увидел на экране: не просто «приложение», а моя собственная CRM, которая показывает клиентов.
Я помню этот момент. Когда я нажал «Добавить», ввёл имя и телефон, нажал «Сохранить» — и…
А об этом вы узнаете в следующей статье цикла.