What's the right place for business logic?

You're working on your own version of stackoverflow :-)

You're using ASP.NET MVC and Entity Framework (model-first approach if it matters). So, you have a couple of classes generated by EF:

class Question {...}
class Answer {...}

You also has all the related stuff (ObjectContext, etc). You have all the related code to handle a scenario of answering the question (StackoverflowController with AnswerQuestion[get] + AnswerQuestion[post] actions, also a view to display a fancy form - Stackoverflow/Answer).

Your customer is a very tough guy, so he defines a set of business rules:

  1. Nobody should be able to answer the question in first 5 minutes after the question is asked (they should get a message).
  2. When the answer is posted, topic starter should receive a notification.
  3. The main page should display 20 latest questions.
  4. When displaying answers for every question, they should be ordered by votes.
  5. When questions are downvoted with total of -10, they should be closed.
  6. When answers are downvoted with total of -10, their posters should get anti-bonus of -20 to their reputation.

etc.

The question is - given the facts described above, where would you implement your customer's business rules?

I don't really like the idea of having the code like:

public class HomeController : Controller
{
    ...
    public ActionResult Index()
    {
        return View(_container.Questions.OrderByDescending(x => x.Posted).Take(20).ToList());
    }
}

But how would you name the right place for this logic? And what interface should it have? Is it something like this:

// implements the business logic, interacts with repositories
public static class Stackoverflow
{
    public static IEnumerable<Question> GetRecentQuestions() { ... } // logic here!
    public static void PostAnswer(Question question, Answer answer) { ... } // logic here!
}

?

Answers


One solution is to use a service layer to handle this for you:

public Interface IStackoverflowService
{
    IEnumerable<Question> GetRecentQuestions();
    void PostAnswer(Question question, Answer answer);
}

public class StackoverflowService : IStackoverflowService
{
    private StackoverflowDbContext _container;

    public StackoverflowService(StackoverflowDbContext container)
    {
        _container = container;
    }

    public IEnumerable<Question> GetRecentQuestions() 
    { 
         var model = _container.Questions.OrderByDescending(x => x.Posted);
         return model.Take(20);
    } 

    public void PostAnswer(Question question, Answer answer) { ... }
}

Then in your controller:

public class HomeController : Controller
{
    private IStackoverflowService _stackoverflowService;

    public HomeController(IStackoverflowService stackoverflowService)
    {
        _stackoverflowService = stackoverflowService;
    }

    public ActionResult Index()
    {
        var model = _stackoverflowService.GetRecentQuestions();
        return View(model);
    }
}

You can even break it out into multiple services such as a QuestionsService, an AnswersService, a UsersService, etc.


Need Your Help

Visual Basic C# windows form background worker object movement loop not functioning as intended

c# winforms visual-studio-2012 backgroundworker

I'm currently attempting to write a classic snake sort of game, where the user directs the snake around the screen using the keyboard's arrow keys. So far, i've managed to sort out the code that di...