1
\$\begingroup\$

In order to better understand what the code does, I've captured this screencast.

Basically, I have a products page and a user can filter products.

CODE

Here is the Page action method on my ProductController:

public ActionResult Page(SearchViewModel search, int page = 1)
{
  var viewModel = _productService.GetPagedProducts(search, page);
  PopulateDropDownSelectListsForSearchVm(viewModel.Search);
  return View(viewModel);
}

That PopulateDropDownSelectListsForSearchVm is a helper method that sits within the controller.

Here is the implementation of the GetPagedProducts method on the IProductService interface:

public ProductPageViewModel GetPagedProducts(SearchViewModel search, int page = 1)
{
  int totalNumberOfProducts;
  if (HaveSearchTermsChanged(search)) page = 1;
  var products = _context.Products.Where(p => p.IsDeleted == search.ShowDeleted).AsQueryable();
  if (search.CategoryId != 0) products = products.Where(p => p.CategoryId == search.CategoryId);
  if (search.BrandId != 0) products = products.Where(p => p.BrandId == search.BrandId);
  if (search.QualityId != 0) products = products.Where(p => p.QualityId == search.QualityId);

  if (!string.IsNullOrEmpty(search.SearchTerm))
  {
    products = products
                .Where(p => p.Name == search.SearchTerm.Trim())
                .OrderBy(p => p.Name);
    totalNumberOfProducts = products.Count();
    products = products.Skip(_recordsPerPage * (page - 1)).Take(_recordsPerPage);
  }
  else
  {
    products = products.OrderBy(p => p.Name);
    totalNumberOfProducts = products.Count();
    products = products.Skip(_recordsPerPage * (page - 1)).Take(_recordsPerPage);
  }

  var productPageVm = new ProductPageViewModel
  {
    Products = ProductViewModelFactory.BuildListOfProductViewModels(products.ToList()),
    Pagination = new PaginationViewModel
    {
      CurrentPage = page,
      RecordsPerPage = _recordsPerPage,
      TotalRecords = totalNumberOfProducts
    },
    Search = search
  };

  TrackCurrentSearchTerm(productPageVm);
  return productPageVm;
}

Readability is really important to me, and right now it just doesn't feel readable. What can I do to improve the overall code, and have it be very readable?

\$\endgroup\$
3
  • \$\begingroup\$ What aspects of 'readability' are you concerned about. Its looks fine, although there are a few areas where the code could be simplified (for example, if (HaveSearchTermsChanged(search)) page = 1; is pointless and you could move your .OrderBy(p => p.Name);, totalNumberOfProducts = products.Count(); and products = products.Skip(_recordsPerPage * (page - 1)).Take(_recordsPerPage); lines to after the if block and delete the else block \$\endgroup\$ Commented Nov 10, 2017 at 0:38
  • \$\begingroup\$ In addition, your checks for the value of the 3 dropownlists (e.g. if (search.CategoryId != 0) suggests you not generating them correctly and because the 'label' option should be null, not 0 \$\endgroup\$ Commented Nov 10, 2017 at 0:41
  • \$\begingroup\$ Note also you do not need .AsQueryable() - it already is \$\endgroup\$ Commented Nov 10, 2017 at 0:42

1 Answer 1

0
\$\begingroup\$

I would suggest you to move the pagination settings to your SearchModel

Then you can have an utility/extension method or whatever you whish with this signature

public IQueryable<Product> ApplyFilter(IQueryable<Product> productQuery, SearchModel model)

and you write there ll the filtering business, so you can re use it in more methods and simplify the readability of your main method.

Finally, I would not recommend to rewrite your if statements like this

if (search.CategoryId != 0)
{
    products = products.Where(p => p.CategoryId == search.CategoryId);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.