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...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.