根据角色限制用户可以执行的操作

时间:2011-07-04 18:20:57

标签: c# oop architecture mvvm single-responsibility-principle

方案

我正在构建一个系统,每个项目都由2个不同的人进行审核。每当第一个评论者保存项目评论时,它就会转向第二个检查者完成他们的个人评论。如果我提交了第一次审核并再次打开该项目,则该项目将进入只读状态,因为您无法查看自己的工作。此外,如果需要更多信息,第一个评论者可以将项目置于待定状态,而第二个评论则不能。每当用户从列表中选择一个项目时,每个用户都会获得一个特定的审阅者滚动。

到目前为止我有什么

每次将一个项目加载到编辑器中时,该人员将被赋予两个角色InitialReviewerSecondReviewer中的一个。

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);
    }
}

我的编辑器的精简版。

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");
    }
}

问题

我遇到的问题是,我似乎无法摆脱Save()Editor中不属于那里的逻辑。

问题

如何摆脱Save()类中Editor函数内部的逻辑?它似乎违反了SRP原则。我认为检查当前审阅者对象是否为ICanPutIntoPendingState类型是个大问题。

请注意,我已经省略了所有逻辑,因为它有很多。

2 个答案:

答案 0 :(得分:3)

Woudn足以向ReviewerService提供一个Save()方法,该方法在此时内部调用一个Save()方法,抽象类Reviewer,用于抽象Save()方法的具体实现在InitialReviewer和SecondReviewer中创建。因此,您可以通过具体实现将决策逻辑推送到类。 希望这会有所帮助。

答案 1 :(得分:2)

也许你应该考虑将业务逻辑从Reviewer类移到ReviewerService。简单的实现将是这样的:

    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");
    }
}

您还可以考虑在审阅者服务上仅公开一个带有输入模型的函数。然后,服务负责验证输入并采取适当的措施。像这样:

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);
    }
}