开发者

Limiting what a user can do based on roles

开发者 https://www.devze.com 2023-03-17 09:37 出处:网络
Scenario I\'m building a system where each item gets reviewed by 2 different people. Whenever the first reviewer saves an item review it\'s then turn for the second checker to complete their individu

Scenario

I'm building a system where each item gets reviewed by 2 different people. Whenever the first reviewer saves an item review it's then turn for the second checker to complete their individual review. If I submitted the first review and I open the item again then the item is put into a read only state because you can't review your own work. Also, the first reviewer can put the item into a pending state if more information is required, which the second review can't. Each user is given a specific reviewer roll whenever they select an item from a list.

What I have so far

Each time an item is loaded into the editor the person is given one of 2 roles, InitialReviewer or SecondReviewer.

public class Reviewer
{
    public void AddReview(string review) { }
}

public class InitialReviewer : Reviewer, ICanPutIntoPendingState
{
    public void PutIntoPendingState(string pendingState) { }
}

public class SecondReviewer : Reviewer
{
    // Just use base class to add review
}

public class ReviewerService
{
    private readonly Reviewer _reviewer;

    public void AddReview(string review)
    {
        _reviewer.AddReview(review);
    }

    public void PutIntoPendingState(string pendingState)
    {
        _reviewer.PutIntoPendingState(pendingState);
    }
}

A trimmed down version of my editor.

public class Editor
{
    private readonly ReviewerService _reviewerService;

    public Editor(ReviewerService reviewerService)
    {
        _reviewerService = reviewerService;
    }

    public void SaveCommand()
    {
        if(user chose a pending state && _reviewerService.Reviewer is ICanPutIntoPendingState) // Pending state is a dropdown.
            _reviewerService.PutIntoPendingState("pending state");
        else // the user made a complete review
            _reviewerService.AddReview("user review");
    }
}

Problem

The issue I'm having is that I can't seem to escape from having logic inside Save() from the Editor class that doesn't belong there.

Question

How do I rid myself of the logic inside of the 开发者_StackOverflow中文版Save() function from the Editor class? It appears to be violating the SRP principle. Checking whether the current reviewer object is of type ICanPutIntoPendingState is the big problem, I think.

Note that I've ommited all logic because there's quite a bit.


Woudn't be enough to give to ReviewerService one Save() method, which internaly call one Save() method of, at this point, abstract class Reviewer, whom abstact Save() method's concrete implementation is made in InitialReviewer and SecondReviewer. So you push decisional logic to classes with concrete implementation. Hope this helps.


Perhaps you should consider moving business logic from Reviewer class to ReviewerService. Simple implementation would be then something like this:

    public abstract class Reviewer
{
    public abstract bool CanPutIntoPendingState { get; }

}

public class InitialReviewer : Reviewer
{
    public override bool CanPutIntoPendingState 
    {
        get
        {
            return true;
        }
    }
}

public class SecondReviewer : Reviewer
{
    public override bool CanPutIntoPendingState 
    {
        get
        {
            return false;
        }
    }
}

public class ReviewerService
{
    private readonly Reviewer _reviewer;

    public void AddReview(string review)
    {
        // do add review logic here
    }


    public void PutIntoPendingState(string pendingState) 
    { 
        if (_reviewer.CanPutIntoPendingState ) 
        {
            // do PutIntoPendingState logic here
        }
    }
}

public class Editor
{
    private readonly ReviewerService _reviewerService;

    public Editor(ReviewerService reviewerService)
    {
        _reviewerService = reviewerService;
    }

    public void SaveCommand()
    {
        if(user chose a pending state) // Pending state is a dropdown.
            _reviewerService.PutIntoPendingState("pending state");
        else // the user made a complete review
            _reviewerService.AddReview("user review");
    }
}

You can also consider to expose only one function on reviewer service, that takes input model. Service is then responsible to validate input and take appropriate action. Something like this:

public class ReviewerService
{
    private readonly Reviewer _reviewer;

    public void StoreReview(ReviewModel model)
    {
        // validate input here

        // do business logic here
        if (model.IsPendingState && _reviewer.CanPutIntoPendingState)
        {
            this.PutIntoPendingState("pending state");
        }
        else
        {
            this.AddReview(model.Review);
        }

    }

    private void AddReview(string review)
    {
        // do add review logic here
    }

    private void PutIntoPendingState(string pendingState)
    {

       // do PutIntoPendingState logic here

    }
}

public class ReviewModel
{
    public string Review { get; set; }
    public bool IsPendingState { get; set; }
}

public class Editor
{
    private readonly ReviewerService _reviewerService;

    public Editor(ReviewerService reviewerService)
    {
        _reviewerService = reviewerService;
    }

    public void SaveCommand()
    {
        ReviewModel model = new ReviewModel() {Review="user review",IsPendingState=user chose a pending state };

        _reviewerService.StoreReview(model);
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号