我有一个ASP.NET MVC应用程序使用控制器和操作上的授权属性.这一直运作良好,但出现了新的皱纹.
对象:装运
角色:航运,会计,一般用户
装运在工作流程中移动.在状态A中,它只能由Shipping进行编辑.在状态B中,它只能通过会计编辑.
我有一个ShipmentController和一个Edit Action.我可以使用Authorization属性将Edit操作限制为仅限于这两个角色,但这并不区分Shipment所处的状态.我需要在服务调用之前在操作内部执行一些授权以确定用户是否真的有权执行编辑操作.
所以我有两个问题:
1)在Action中获得授权的好方法.Controller Action调用服务,然后服务对Shipment对象进行适当的调用(更新数量,更新日期等).我确信我希望Shipment对象不受任何授权要求的影响.另一方面,如果我希望服务对象知道授权,我没有真正掌握.这有什么好的模式吗?
2)我的问题实际上是设计糟糕的症状吗?我应该有一个StateAShipmentController和StateBShipmentController而不是ShipmentController吗?我没有在Shipment对象中内置任何多态性(状态只是一个枚举),但也许我应该,也许控制器应该反映出来.
我想我会采用更一般的解决方案,而不是针对我的情况.我只想提供一个例子来说明这个问题.
谢谢!
model-view-controller asp.net-mvc authorization design-patterns single-responsibility-principle
维基百科以这种方式描述单一责任原则:
单一责任原则规定每个对象应该只有一个责任,并且该责任应该由类完全封装.其所有服务应与该责任严格一致.
MVC中控制器的传统使用似乎导致程序员违反了这一原则.拿一个简单的留言簿控制器和视图.控制器可能有两个方法/操作:1)Index()和2)Submit().Index()显示表单.Submit()处理它.这两种方法是否代表两种不同的责任?如果是这样,单一责任如何进入?
model-view-controller single-responsibility-principle solid-principles
我可以通过封装,依赖注入,最少知识原则,你不需要它来掌握"做一件事"的部分; 但我怎么理解第二部分"做得好"?
给出的一个例子是完整性的概念,在同一篇YAGNI文章中给出:
例如,在允许添加项目,删除项目或修改项目的特征中,可以使用完整性来推荐"重命名项目".
但是,我发现这样的推理很容易被滥用到特征蠕变中,从而违反了"做一件事"的部分.
因此,看到相当一个特征属于"做得好"类别(因此,将其包含在函数/类/程序中)或其他"做一件事"类别(因此,排除它)的试金石是什么? ?
第一部分,"做一件事",最好通过UNIX的ls命令来理解,因为它包含了过多的标志来格式化它的输出,这些标志本应完全委托给另一个外部程序.但我没有一个很好的例子来看第二部分"做得好".
什么是一个很好的例子,删除任何进一步的功能将使它不"做得好"?
在我的应用程序设计中,我通常将对象映射到数据库中的重要表.然后,对象处理与该数据相关的所有内容(包括链接表).因此,我例如已经建立了一个Activity对象,具有类似性质name和due_date,方法等load()和save(),并且还方法等getParent(),getContributors()并且getTeam(),其返回(阵列)的其他对象.这是"坏"OOP,因为它违反了单一责任原则吗?
我越是使用Symfony2并且与它的形式斗争越多,我得出的结论是它们是一个巨大的可怕的野兽,甚至不应该存在.
我在这里发现了这篇文章 ,我发现我同意作者.即使文章是Symfony的1.x的,我认为它仍然适用于在Symfony2中的表单组件.看起来表单组件似乎试图在一个地方解决属于模板,控制器和模型的问题.这不是严重违反MVC和/或SRP(单一责任原则)吗?
这可能是一个不同的问题,但我觉得它有点相关 - 我也注意到symfony的许多可用包试图解决视图外的视图问题,例如:
KnpMenuBundle - 您在服务器端使用oo接口生成菜单(为什么不在它们所属的视图层中?)
IvoryCKEditorBundle - 将textarea转换为ckeditor是在视图文件中的一个jquery行中完成的,那么为什么这个bundle存在呢?我甚至不想计算那里的行数.
因此,那种好像有在Symfony的核心遍地都是这些违规还是我只是没有得到它?
php model-view-controller design-patterns single-responsibility-principle symfony
我有一种算法可以为实体创建一个版本,然后将其保存在下面的2个实体中:
1)变体
2)类别
interface IEntityVersion
{
string GetVersion();
}
public class EntityVersion : IEntityVersion
{
public string GetVersion()
{
return null;
}
}
public interface IVariant
{
void Process(Variant model, string connectionString);
}
public abstract class BaseVariant : IVariant
{
private readonly IEntityVersion _entityVersion = new EntityVersion();
public void Process(Variant model, string connectionString)
{
try
{
Transform();
string variantVersion = _entityVersion.GetVersion();
using (var myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
using (var transaction = myConnection.BeginTransaction())
{
try
{
VariantRepo.UpdateVariantVersion(
myConnection,
transaction, …Run Code Online (Sandbox Code Playgroud) 我有一堆键和值,我想通过将它们打包到一个字节数组中发送到我们的消息队列.我将创建所有键和值的一个字节数组,该数组应始终小于50K,然后发送到我们的消息队列.
包类:
public final class Packet implements Closeable {
private static final int MAX_SIZE = 50000;
private static final int HEADER_SIZE = 36;
private final byte dataCenter;
private final byte recordVersion;
private final long address;
private final long addressFrom;
private final long addressOrigin;
private final byte recordsPartition;
private final byte replicated;
private final ByteBuffer itemBuffer = ByteBuffer.allocate(MAX_SIZE);
private int pendingItems = 0;
public Packet(final RecordPartition recordPartition) {
this.recordsPartition = (byte) recordPartition.getPartition();
this.dataCenter = Utils.LOCATION.get().datacenter();
this.recordVersion = 1;
this.replicated = …Run Code Online (Sandbox Code Playgroud) java oop design-patterns bytebuffer single-responsibility-principle
我有YoutubeVideoService执行 CRUD(创建、读取、更新和删除)操作的类。在我看来,创建、读取、更新和删除是类更改的四个原因。这个类是否违反了单一职责原则?
如果违反,那么,我们应该有四个类,如CreateYoutubeVideoService,ReadYoutubeVideoService,UpdateYoutubeVideoService和DeleteYoutubeVideoService。有很多课程是不是有点矫枉过正?
我最近一直在考虑Liskov替换原则以及它与我当前任务的关系.我有一个包含菜单的主表单; 在这个主要表单中,我将一个特定的表单作为MDI子对接.此特定表单可能包含也可能不包含菜单.如果是,我想将它与主菜单合并.所以情况是这样的:
public class MainForm
{
public void Dock(SpecificBaseForm childForm)
{
this.Dock(childForm);
if (childForm is IHaveMenu)
{
this.Menu.Merge(childForm as IHaveMenu).Menu;
}
}
}
public interface IHaveMenu
{
Menu Menu {get;}
}
public abstract class SpecificBaseForm{}
public class SpecificFormFoo : SpecificBaseForm {}
public class SpecificFormBar: SpecificBaseForm,IHaveMenu
{
public Menu Menu{get {return this.Menu;}}
}
Run Code Online (Sandbox Code Playgroud)
现在这两个孩子并不是"完全"可互换的:一个有菜单; 另一个没有.这是在C#中误用is/as contruct吗?如果这不正确,那么干净的解决方案是什么?
c# design-patterns single-responsibility-principle design-principles solid-principles
在实现我的课程之后,目前处于实质性的重构工作中.我试图分解一些事情,更好地遵循SRP,但我总是发现很难评估一个班级是否有"改变的一个理由"的格言.我希望这个实际的例子可以帮助我理解.
有问题的代码旨在清理数据.目前这里有两个独立的进程 - 我们通过使用通过代码调用的外部应用程序来清理地址数据.我们使用C#中的内部算法清理其他数据字段.
当我被告知我们可能希望将来更改这两个进程时,这个重构就开始了 - 例如,使用数据库存储过程来执行这两个作业而不是C#代码和外部应用程序.所以我的第一直觉是将这两个函数隐藏在接口后面(FileRow并且FileContents只是DTO):
public interface IAddressCleaner
{
string CleanAddress(StringBuilder inputAddress);
void CleanFile(FileContents fc);
}
public interface IFieldCleaner
{
string CleanPhoneNumber(string phoneToClean);
void CleanAllPhoneFields(FileRow row, FileContents fc);
void MatchObscentities(FileRow row, FileContents fc);
void CleanEmailFields(FileRow row, FileContents fc);
}
Run Code Online (Sandbox Code Playgroud)
哪个好.然而,实际上,我无法想象一个班级会在没有其他班级的情况下使用其中一个.因此将它们(及其实现)合并到一个类中似乎是有意义的.这也是有道理的,因为我们可以用一个解决方案(如数据库)替换这两个函数.
另一方面,似乎IFieldCleaner已经违反了SRP,因为它正在做三件事:清理电话号码,发送电子邮件和寻找粗鲁的话语,所有这些都是逻辑上不同的过程.所以似乎有理由把它分成一个IPhoneCleaner,IObscenityMatcher和IEmailCleaner.
对后一种方法特别困扰的是这些类在服务中使用,该服务已经具有愚蠢的接口依赖性:
public class ReadFileService : IExecutableObject
{
private ILogger _log;
private IRepository _rep;
private IFileHelper _fileHelp;
private IFieldCleaner _fieldCleaner;
private IFileParser _fileParser;
private IFileWriter _fileWriter; …Run Code Online (Sandbox Code Playgroud) c# architecture interface single-responsibility-principle solid-principles
single-responsibility-principle ×10
c# ×3
oop ×3
php ×2
.net ×1
architecture ×1
asp.net-mvc ×1
bytebuffer ×1
interface ×1
java ×1
refactoring ×1
symfony ×1
yagni ×1