Открытие рубрики «Совершенный код»

10 мая 2010 г.

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

Я решил открыть рубрику «Совершенный код». Каждую неделю буду выкладывать проблемный код, вопросы по архитектуре или тестированию, которые вы мне присылаете. Вы можете находить проблемы в коде и описывать пути их решения. Через неделю я выложу лучшие советы со ссылкой на авторов и возможно своими дополнениями. Авторы решений, оставляйте, пожалуйста, свои контакты (сайты, блоги), чтобы я мог на вас ссылаться.

Начали!

Приложение написано на ASP.NET MVC. Мне прислали небольшой кусочек кода, связанный с редактирование отчёта. У автора возникли проблемы с изменением этого кода, написанием на него тестов и работой с моделью (M-V-C).

Контроллер ReportersController

   1:  public class ReportersController : Controller
   2:  {
   3:      Linq2SqlDataContext dataContext;
   4:   
   5:      public ReportersController() 
   6:      {
   7:          dataContext = new Linq2SqlDataContext();
   8:      }
   9:   
  10:      // ...
  11:   
  12:      // форма редактирования
  13:      public ActionResult Edit(int id) 
  14:      {
  15:          var item = dataContext.Reporters.FirstOrDefault(x => x.Id == id);
  16:          return View(new ReporterFormViewModel(item));
  17:      }
  18:   
  19:      [HttpPost]
  20:      public ActionResult Edit(int id, Reporter reporter, string saveAndExit, string saveAndStay) 
  21:      {
  22:          var item = dataContext.Reporters.FirstOrDefault(x => x.Id == id);
  23:   
  24:          if (ModelState.IsValid) 
  25:          {
  26:              try
  27:              {
  28:                  UpdateModel(item, "reporter");
  29:   
  30:                  dataContext.SubmitChanges();
  31:   
  32:                  if (saveAndExit == null)
  33:                      return RedirectToAction("Edit", new { id });
  34:   
  35:                  return RedirectToAction("Index");
  36:              }
  37:              catch (Exception ex) 
  38:              {
  39:                  ModelState.AddModelError("formReport", ex.Message);
  40:   
  41:                  return View(new ReporterFormViewModel(reporter));
  42:              }
  43:          }
  44:          
  45:          return View(new ReporterFormViewModel(reporter));
  46:      }
  47:  }

Модель ReporterFormViewModel

   1:  public class ReporterFormViewModel
   2:  {
   3:      public ReporterFormViewModel() : this(new Reporter() { CreatedDate = DateTime.Now }) 
   4:      {
   5:      }
   6:   
   7:      public ReporterFormViewModel(Reporter reporter) 
   8:      {
   9:          Reporter = reporter;
  10:   
  11:          InitCollections();
  12:      }
  13:   
  14:      private void InitCollections()
  15:      {
  16:          var dataContext = new Linq2SqlDataContext();
  17:   
  18:          Publications = dataContext.Publications.Select(x => new SelectListItem() {
  19:              Value = x.Id.ToString(),
  20:              Text = x.Name
  21:          });
  22:      }
  23:   
  24:      public IEnumerable<SelectListItem> Publications { get; set; }
  25:      
  26:      public Reporter Reporter { get; set; }
  27:  }

Тестов к коду, к сожалению, нет. Да-да, я понимаю, что делать рефакторинг без тестов довольно сложно.

Хочу заметить, что разработчики, которые могут признать, что в их коде есть проблемы, имеют все шансы стать лучше и узнать что-то новое. Надо иметь смелость, чтобы просить помощи. Поэтому в комментариях к коду приветствуется конструктив и позитив!


Разбор решения к выпуску №1

Моя книга «Антихрупкость в IT»

Как достигать результатов в IT-проектах в условиях неопределённости. Подробнее...