dns*_*_nx 5 c# solid-principles
我目前是清洁代码和 SOLID 原则主题的新手。
我们已经UseCase为特定任务编写了一个。
using BusinessLogic.Classes.BusinessLogic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLogic.UseCases
{
public class DoASpecificTask<T> : Interfaces.IUseCase
where T : Interfaces.Connections.IQuery
{
T _Query;
Interfaces.Connections.IConnection<T> _Connection;
object _Parameters;
string _ServiceName;
Interfaces.ISendMessage _MessageSender;
public DoASpecificTask(T query, Interfaces.Connections.IConnection<T> connection, object parameters, string serviceName, Interfaces.ISendMessage messageSender)
{
_Query = query;
_Connection = connection;
_Parameters = parameters;
_ServiceName = serviceName;
_MessageSender = messageSender;
}
public void Execute()
{
Interfaces.Connections.IQueryResultList resultList = ExecuteReadDataOnConnection<T>.GetList(_Query, _Connection, _Parameters);
if (!ValidateQueryResultListItems.Validate(resultList))
{
EndImp3Service.EndService(_ServiceName);
_MessageSender.SendMessage('Message','for@bar.com');
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
据我了解 SOLID,解决方案/类/方法应该对扩展开放,对更改关闭(开放/封闭原则)。我们现在的问题是,我们已经创建了一个非特定的通用interface消息来发送消息
Interfaces.ISendMessage:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLogic.Interfaces
{
public interface ISendMessage
{
void SendMessage(string message, string recipient);
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,我们想通过电子邮件发送消息,因此我们创建了另一个接口ISendEmail,它实现了ISendMessage. 一封电子邮件也有一个参数subject,它在通用接口ISendMessage(方法SendMessage())中没有实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLogic.Interfaces
{
public interface ISendEmail : ISendMessage
{
void SendMessage(string message, string recipient, string subject);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,我们怎么能不具体UseCase地保持开放以进行扩张?可能在某个时候我们想要发送 WhatsApp 或 Telegram 消息而不是电子邮件。如果我执行的财产ISendMessage的UseCase,我没有参数subject。
我的意思是UseCase:
_MessageSender.SendMessage('Message','for@bar.com');
Run Code Online (Sandbox Code Playgroud)
因为我们指定了通用接口ISendMessage,所以不能subject在方法中提供a 。如果我们更改ISendMessage为ISendEmail,我们就不再开放了,不是吗?
如何做到这一点,或者我们是否误解了完全错误的事情?
首先,感谢您的意见和解决方案。我认为,这正是我们作为 SOLID 初学者需要了解的问题,什么时候要具体,而不是试图制作一个在任何情况下都可以做任何事情的程序。当然,SOLID并不是说完全不改代码,问题是代码需要改到哪里。
我认为,在所有提供的解决方案中,问题只是转移了。无论如何,我需要指定我在UseCase. 如果我要使用@Martin Verjans 的解决方案,我可以使用 type IMessage,但是我必须在参数中具体说明。通过使用generics,我有同样的问题。@SomeBody 的解决方案,不符合开闭原则。
我们的目标是实现是在非特异性的UseCase,所以我们并不需要改变UseCase自己,如果我们决定发送WhatsApp的消息,而不是电子邮件。实际上我没有看到这个选项。
您可以修改您的界面ISendMessage,让它知道它是否支持某个主题:
public interface ISendMessage
{
bool SupportsSubject { get; }
void SendMessage(string message, string recipient);
void SendMessage(string message, string recipient, string subject);
}
Run Code Online (Sandbox Code Playgroud)
你会这样称呼它:
if(_MessageSender.SupportsSubject)
{
_MessageSender.SendMessage("Message","for@bar.com", "the subject");
}
else
{
_MessageSender.SendMessage("Message","for@bar.com");
}
Run Code Online (Sandbox Code Playgroud)
这种方式也用在基类库中。例如,该类Stream有一个名为 的属性CanSeek。当然,如果您在接口的实现中有多个这样的可选参数,那么这将变得不切实际,因为这将导致大量的 if 检查。