标签: solid-principles

在尝试遵循SOLID原则时,我的课程设计有多精细?

我有一个名为IRegistrationService的客户端注册界面.这包含一个名为Register的方法,它通过类RegistrationService实现.如果我想要删除,更新,检索方法,我会为每个操作创建一个单独的接口,例如IDeletionService,IUpdateService,IRetrieveService,或者只是将所有方法放入IRegistrationService.我问这个的原因是因为这就是SOLID原则,特别是SRP原则似乎要问的问题.

oop solid-principles

6
推荐指数
1
解决办法
292
查看次数

开源库中OCP的好例子

关于stackoverflow的"开放封闭原则"主题已经有很多讨论.然而,似乎通常对该原理的更宽松的解释是普遍的,因此例如Eclipse可以通过插件进行修改.

根据严格的OCP,您应该修改原始代码只是为了修复错误,而不是添加新的行为.

在公共或OS库中是否有任何严格解释OCP的好例子,你可以通过OCP观察一个特征的演变:有一个类Foo,方法是bar(),而且还有一个FooDoingAlsoX和foo2()方法.库的下一个版本,其中原始类已被扩展,其中原始代码未被修改.

编辑:根据Robert C. Martin的说法:"模块的二进制可执行版本,无论是可链接库,DLL还是Java .jar都保持不变"*.我从未看到库保持关闭,实际上新的行为被添加到库中并且新版本已发布.根据OCP,新行为属于新的二进制模块.

*Robert C. Martin的敏捷软件开发,原则,模式和实践

oop open-closed-principle solid-principles

6
推荐指数
1
解决办法
1253
查看次数

SOLID Essentials遗漏点?

我已经阅读了很多这方面的文章,但我还有两个问题.

问题#1 - 关于依赖性倒置:

它声明高级类不应该依赖于低级类.两者都应该取决于抽象.抽象不应该依赖于细节.细节应取决于抽象.

例如 :

public class BirthdayCalculator
{
    private readonly List<Birthday> _birthdays;

    public BirthdayCalculator()
    {
        _birthdays = new List<Birthday>();// <----- here is a dependency
    }
...
Run Code Online (Sandbox Code Playgroud)

修复:把它放在一个ctor.

public class BirthdayCalculator
{
    private readonly IList<Birthday> _birthdays;

    public BirthdayCalculator(IList<Birthday> birthdays) 
    {
        _birthdays = birthdays;
    }
Run Code Online (Sandbox Code Playgroud)
  • 如果它将在ctor中 - 我将不得不每次使用该课程时发送它.所以在打电话给BirthdayCalculator班级时我必须保留它.它可以这样做吗?

  • 我可以争辩说,在修复之后,仍然 - IList<Birthday> _birthdays不应该在那里(Birthdayin IList) - 但它应该是IList<IBirthday>.我对吗 ?

问题#2 - 关于利斯科夫换人:

派生类必须可替代其基类

或更准确:

设q(x)是关于类型T的对象x可证明的属性.对于类型S的对象y,q(y)应该为真,其中S是T的子类型.

(已经读过这个)

例如:

public …
Run Code Online (Sandbox Code Playgroud)

c# design-patterns liskov-substitution-principle inversion-of-control solid-principles

6
推荐指数
1
解决办法
295
查看次数

当Liskov Substitution引用子类型时,它是否在C#的上下文中讨论派生类?

在查看维基百科文章后,我对"子类型"一词不熟悉.

我把Liskov替换意味着,如果你有接受一个方法Animal,你应该能够在通过CatAnimal在那里Cat : Animal没有任何意想不到的副作用.

这是Liskov替换所指的吗?

c# oop solid-principles

6
推荐指数
1
解决办法
144
查看次数

门面模式与SRP

在经典的Facade模式中,单个对象通常为更复杂的东西提供简化的界面.

正如四人帮所说的那样(尽管接近"官方"......):

Facade(185)为子系统中的一组接口提供统一接口.Facade定义了一个更高级别的接口,使子系统更易于使用.

...一个外观只是抽象出子系统对象的接口,使它们更容易使用; 它没有定义任何新功能,子系统类也不知道它.

或者,正如Unmesh将其放在/sf/answers/366973351/中:

Facade保护用户免受系统的复杂细节的影响,并为他们提供易于使用的简化视图.它还将使用系统的代码与子系统的细节分离,使以后更容易修改系统.

单一责任原则告诉我们

一个类或模块应该只有一个改变的理由.

Per Bob叔叔(http://en.m.wikipedia.org/wiki/Single_responsibility_principle)

鉴于Facade在设计上可以保护用户免受众多"改变的原因"的影响,这两个想法如何协同工作?Facade是否有与其实现所依赖的子系统数量一样多的理由进行更改?

oop design-patterns single-responsibility-principle facade solid-principles

6
推荐指数
2
解决办法
1025
查看次数

开放、封闭与单一责任

我正在研究单一职责原则(SRP)和开闭原则(OCP)。

SRP 规定,一个类必须只有一个改变的理由。OCP 规定类必须对修改关闭,但对扩展开放。

我觉得这是矛盾的。一个原则规定类必须足够简单,您可以出于单一原因进行更改,但另一条原则规定类不得更改而只能扩展。

有人有更好的解释吗?

oop design-patterns solid-principles

6
推荐指数
1
解决办法
2921
查看次数

接口隔离和单一责任原则的问题

我试图遵循接口隔离单一职责原则,但是我对如何将它们整合在一起感到困惑。

在这里,我有一个示例,其中有一些接口,我已将其拆分为更小、更直接的接口:

public interface IDataRead
{
    TModel Get<TModel>(int id);
}

public interface IDataWrite
{
    void Save<TModel>(TModel model);
}

public interface IDataDelete
{        
    void Delete<TModel>(int id);
    void Delete<TModel>(TModel model);
}
Run Code Online (Sandbox Code Playgroud)

我稍微简化了它(有一些where条款妨碍了可读性)。

目前我正在使用SQLite ,但是,这种模式的美妙之处在于,如果我选择不同的数据存储方法(例如Azure),它有望让我有机会更好地适应变化。

现在,我对每个接口都有一个实现,下面是每个接口的简化示例:

public class DataDeleterSQLite : IDataDelete
{
    SQLiteConnection _Connection;

    public DataDeleterSQLite(SQLiteConnection connection) { ... }

    public void Delete<TModel>(TModel model) { ... }
}

... 

public class DataReaderSQLite : IDataRead
{
    SQLiteConnection _Connection;

    public DataReaderSQLite(SQLiteConnection connection) { ... }

    public …
Run Code Online (Sandbox Code Playgroud)

c# interface single-responsibility-principle solid-principles interface-segregation-principle

6
推荐指数
2
解决办法
1623
查看次数

如何在运行时解析类型以避免multipe if else

我有我的代码根据请求类型进行Web服务调用.

为此,我有以下代码;

public class Client
{
    IRequest request;


    public Client(string requestType)
    {
        request = new EnrolmentRequest();
        if (requestType == "Enrol")
        {
            request.DoEnrolment();
        }
        else if (requestType == "ReEnrol")
        {
            request.DoReEnrolment();
        }
        else if (requestType == "DeleteEnrolment")
        {
            request.DeleteEnrolment();
        }
        else if (requestType == "UpdateEnrolment")
        {
            request.UpdateEnrolment();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

所以按照开放原则,我可以像子类一样子类:

Class EnrolmentRequest:IRequest
{
    CallService();
}
Class ReEnrolmentRequest:IRequest
{
    CallService();
}
Class UpdateEnrolmentRequest:IRequest
{
    CallService();
}
Run Code Online (Sandbox Code Playgroud)

现在我的客户端类看起来像这样:

public class Client
{
    public Client(string requestType)
    {
        IRequest request;

        if (requestType == "Enrol") …
Run Code Online (Sandbox Code Playgroud)

.net c# dependency-injection inversion-of-control solid-principles

6
推荐指数
3
解决办法
203
查看次数

IS-A和Liskov替代原则之间的区别?

我只是想知道IS-A(UML术语和OOP)和Liskov替换原则(LSP)之间是否存在差异?

实际上,两者都在谈论继承.那么实践中的主要区别是什么?

oop inheritance liskov-substitution-principle solid-principles

6
推荐指数
1
解决办法
698
查看次数

这个先决条件是否违反了里氏替换原则

我有 3 个班级,Account, CappedAccount, UserAccount,

CappedAccount,并且UserAccount都扩展Account

Account 包含以下内容:

abstract class Account {
   ...
   /**
   * Attempts to add money to account.
   */
   public void add(double amount) {
      balance += amount;
   }
}
Run Code Online (Sandbox Code Playgroud)

CappedAccount 覆盖此行为:

public class CappedAccount extends Account {
   ...
   @Override
   public void add(double amount) {
      if (balance + amount > cap) { // New Precondition
         return;
      }
      balance += amount;
   }
}
Run Code Online (Sandbox Code Playgroud)

UserAccount不会覆盖来自 的任何方法Account,因此不需要说明。

我的问题是,是否CappedAccount#add …

java oop design-patterns solid-principles

6
推荐指数
1
解决办法
167
查看次数