C# 这是否正确执行单一责任原则
我想知道这是否是单一责任原则的最佳方法。 此类的职责是提醒由于不活动而导致帐户即将过期的用户 在不活动的30天内,用户会收到一封电子邮件。 在不活动的45天内,用户没有收到电子邮件,他们被禁用C# 这是否正确执行单一责任原则,c#,asp.net,asp.net-mvc,entity-framework,C#,Asp.net,Asp.net Mvc,Entity Framework,我想知道这是否是单一责任原则的最佳方法。 此类的职责是提醒由于不活动而导致帐户即将过期的用户 在不活动的30天内,用户会收到一封电子邮件。 在不活动的45天内,用户没有收到电子邮件,他们被禁用 public class AccountReminder { private readonly IUnitOfWork _uow; private readonly ISendExpiringEmail _sendExpiringEmail; public AccountRem
public class AccountReminder
{
private readonly IUnitOfWork _uow;
private readonly ISendExpiringEmail _sendExpiringEmail;
public AccountReminder(IUnitOfWork uow, ISendExpiringEmail sendExpiringEmail)
{
_uow = uow;
_sendExpiringEmail = sendExpiringEmail;
}
public void NotifyUpcomingExpiringAccounts()
{
// Establish dates
DateTime accountWarningDateTime = DateTime.Now.AddDays(-30).Date;
DateTime expirationDateTime = DateTime.Now.AddDays(-45).Date;
// Retrieve users whose accounts are either about to expire or have already expired
var users = _uow.UserRepository
.FindBy(element => (DbFunctions.TruncateTime(element.LastLoginDate) == accountWarningDateTime));
// Send a reminder
foreach (var user in users)
{
string htmlBody = "<html xmlns:v=\"urn:...xmlns=\"http://www.w3.org/TR/REC-html40\" >";
htmlBody += "<head><meta http-equiv=...</head>";
htmlBody += "<body>";
//following line for only outlook to display image
htmlBody += "<v:shape id=\>...</v:shape>";
htmlBody += "<table width='100%'...</table>";
htmlBody += "</body></html>";
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);
AlternateView plainView = AlternateView.CreateAlternateViewFromString(htmlBody, null, "text/plain");
LinkedResource pic1 = new LinkedResource("images/Logo.jpg", MediaTypeNames.Image.Jpeg);
pic1.ContentId = "Logo";
htmlView.LinkedResources.Add(pic1);
_sendExpiringEmail.SendTo(new[] { user.Email }, "EmailSubject", htmlView, plainView);
}
DisableExpiringAccounts(expirationDateTime);
}
private void DisableExpiringAccounts(DateTime expirationDateTime)
{
var expiredUsers = _uow.UserRepository.FindBy(element => element.Enabled && (DbFunctions.TruncateTime(element.LastLoginDate) <= expirationDateTime));
foreach (var user in expiredUsers)
{
user.Enabled = false;
}
if (expiredUsers.Count > 0)
{
_uow.SaveChanges();
}
}
}
公共类帐户提醒
{
私人只读IUnitOfWork;
私人只读邮件发送过期电子邮件;
公共帐户提醒(IUnitOfWork uow、iSendeExpiregeMail发送过期电子邮件)
{
_uow=uow;
_sendExpiringEmail=sendExpiringEmail;
}
public void NotifyUpcomingExpiringAccounts()
{
//确定日期
DateTime accountWarningDateTime=DateTime.Now.AddDays(-30).Date;
DateTime expirationDateTime=DateTime.Now.AddDays(-45).Date;
//检索帐户即将过期或已过期的用户
var users=\u uow.UserRepository
.FindBy(element=>(DbFunctions.TruncateTime(element.lastloginandate)==accountWarningDateTime));
//发送提醒
foreach(用户中的var用户)
{
字符串htmlBody=“element.Enabled&&(DbFunctions.TruncateTime(element.LastLoginDate)0)
{
_uow.SaveChanges();
}
}
}
我认为你对责任的理解太高了。这是一个常见的问题。罗伯特·马丁建议对其进行解释:
单一责任原则(SRP)规定,每个软件模块都应该有一个且只有一个更改原因
以及(同一链接):
在编写软件模块时,您希望确保在请求更改时,这些更改只能来自单个人员,或者更确切地说,来自表示单个狭义定义的业务功能的单个紧密耦合的人员组
在您的示例中,业务需求的更改可能涉及:
- 帐户过期机制背后的逻辑
- 用于通知用户的通信通道
- 消息的格式
-验证帐户是否已过期并禁用它的部分,如果是,可能只有一个实现IAccountExpirationAgent
-发送电子邮件(例如IAccountExpirationNotifier
)或SMS消息等的类AccountExpirationEmailNotifier
-格式化消息的类(例如,IAccountExpirationMessageFormatter
,AccountExpirationMessageHtmlFormatter
)AccountExpirationMessagePlainTextFormatter
确实,这个问题应该发布在上,但我仍然想提供一些建议 这可能是错误的;但我对单一责任原则的理解是“一种方法应该有一份工作”。这使得我们无法编写一个600行的方法来完成所有工作,而且维护起来非常麻烦 更小、更专用(单一责任)的方法更容易维护,因为它们使更大的应用程序更抽象、更容易理解 如果我重写你的课程,我可能会这样做:
- 拆分电子邮件发送功能
- 拆分HTML正文生成;可能会将用户模型发送到Razor视图
公共类帐户提醒
{
私人只读IUnitOfWork;
私人只读邮件发送过期电子邮件;
公共帐户提醒(IUnitOfWork uow、iSendeExpiregeMail发送过期电子邮件)
{
_uow=uow;
_sendExpiringEmail=sendExpiringEmail;
}
public void NotifyUpcomingExpiringAccounts()
{
//确定日期
DateTime accountWarningDateTime=DateTime.Now.AddDays(-30).Date;
DateTime expirationDateTime=DateTime.Now.AddDays(-45).Date;
//检索帐户即将过期或已过期的用户
var users=\u uow.UserRepository
.FindBy(element=>(DbFunctions.TruncateTime(element.lastloginandate)==accountWarningDateTime));
foreach(用户中的var用户)
{
发送提醒(用户);
}
禁用ExpiringAccounts(expirationDateTime);
}
私有无效发送提醒(用户)
{
//将模型传递给视图以生成HTML
//razor实现还应该处理纯文本邮件和html邮件;您可以有两个单独的模板
字符串htmlBody=MyRazorImplementation.GenerateBody(用户);
_sendExpiringEmail.SendTo(新[]{user.Email},“EmailSubject”,htmlView,plainView);
}
私有void DisableExpiringAccounts(DateTime expirationDateTime)
{
var expiredUsers=\u uow.UserRepository.FindBy(element=>element.Enabled&&(DbFunctions.TruncateTime(element.lastloginandate)0)
{
_uow.SaveChanges();
}
}
}
您的问题是代码审查请求,因此更适合您。如果您有关于如何解决特定问题的具体问题,我们很乐意提供帮助。
public class AccountReminder
{
private readonly IUnitOfWork _uow;
private readonly ISendExpiringEmail _sendExpiringEmail;
public AccountReminder(IUnitOfWork uow, ISendExpiringEmail sendExpiringEmail)
{
_uow = uow;
_sendExpiringEmail = sendExpiringEmail;
}
public void NotifyUpcomingExpiringAccounts()
{
// Establish dates
DateTime accountWarningDateTime = DateTime.Now.AddDays(-30).Date;
DateTime expirationDateTime = DateTime.Now.AddDays(-45).Date;
// Retrieve users whose accounts are either about to expire or have already expired
var users = _uow.UserRepository
.FindBy(element => (DbFunctions.TruncateTime(element.LastLoginDate) == accountWarningDateTime));
foreach (var user in users)
{
SendReminder(user);
}
DisableExpiringAccounts(expirationDateTime);
}
private void SendReminder(User user)
{
// pass a model to a view to generate the HTML
// the razor implementation should also handle plain-text vs. html mail; you can have two separate templates
string htmlBody = MyRazorImplementation.GenerateBody(user);
_sendExpiringEmail.SendTo(new[] { user.Email }, "EmailSubject", htmlView, plainView);
}
private void DisableExpiringAccounts(DateTime expirationDateTime)
{
var expiredUsers = _uow.UserRepository.FindBy(element => element.Enabled && (DbFunctions.TruncateTime(element.LastLoginDate) <= expirationDateTime));
foreach (var user in expiredUsers)
{
user.Enabled = false;
}
if (expiredUsers.Count > 0)
{
_uow.SaveChanges();
}
}
}