DevCrm 08 — Когда MainViewModel стал 1300+ строк
Есть момент, который сложно пропустить. Открываешь файл, смотришь на счётчик строк в нижнем углу редактора, и видишь: тысяча тридцать. И это уже не смешно.
У меня этот момент случился с MainViewModel.cs. Открываешь его, а там всё намешано. Авторизация, клиенты, пользователи, задачи, чат, экспорт. Команды, свойства, фильтры, видимость элементов. Всё в одной куче, и понять, где что начинается и где заканчивается, можно только если ты сам это писал неделю назад. А если вернуться через месяц?
Я даже помню, как выглядел этот файл. Одних команд было двадцать шесть штук.
И это только команды. Свойства, поля, методы загрузки, сохранения, удаления, экспорта, бэкапа. Каждое свойство с вызовом OnPropertyChanged. Каждый обёрнутый в try-catch с логированием. Когда количество строк перевалило за тысячу, навигация по файлу превратилась в квест. Чтобы добраться от команды до метода, который она вызывает, нужно было прокрутить триста строк. Пока прокрутишь, уже забываешь, зачем вообще сюда пришёл.
Надо было что-то делать. И тут пригодился partial.
Partial-класс позволяет разбить один класс на несколько файлов. Для компилятора это всё тот же MainViewModel, ничего не меняется. А для разработчика появляются аккуратные разделы, каждый со своим назначением.
Объявление класса остаётся одно:
public partial class MainViewModel : INotifyPropertyChanged { ... }
А дальше в каждом файле своя часть.
public partial class MainViewModel { public bool IsManager => _userService.IsManager(); ... }
Я разбил MainViewModel на несколько файлов:
- MainViewModel.cs — ядро, конструктор, общие свойства, команды.
- MainViewModel.Auth.cs — вход и выход, IsAuthenticated, смена пароля.
- MainViewModel.Clients.cs — загрузка, сохранение, удаление, корзина.
- MainViewModel.Users.cs — управление пользователями и ролями.
- MainViewModel.Tasks.cs — задачи.
- MainViewModel.Chat.cs — чат.
- MainViewModel.Export.cs — экспорт в Excel, Word, PDF.
- MainViewModel.Commands.cs — команды.
- MainViewModel.Visibility.cs — видимость вкладок и панелей.
После этого работать стало проще. Если нужно разобраться с чатом, я открываю Chat.cs. Если проблема с экспортом, открываю Export.cs. Не нужно листать полторы тысячи строк в поисках одного метода.
Но важно понимать: partial это не панацея, а скорее промежуточное решение. Файлы стали меньше, но класс как был большим, так и остался. Разбиение по файлам не заменяет настоящей декомпозиции, когда логика выносится в отдельные сервисы и вьюмодели. Эту работу я делал уже потом, постепенно. И она оказалась куда важнее, чем просто раскладывание по коробочкам.
Однако для начала partial решил главную проблему. Я снова начал понимать, где что лежит. А это, как показывает практика, половина дела, если не больше.
Когда с файлами было покончено, я запустил приложение. Посмотрел на него. И понял, что читаемость кода — это только половина истории. Если смотреть на результат, становится очевидно: есть вещи, которые откладываешь в долгий ящик, а потом они напоминают о себе сами. И вот до них как раз дошла очередь.