项目架构开发:服务层(下)

之前我们已经完成了服务层,因为当时展现层还没有出来,所以只做了简单介绍。传送门:项目架构开发:服务层(上)

这次我们通过一个维护系统用户的场景来介绍一下服务层真正的设计用意。

 

1、新增用户场景

 新增用户可能会有以下步骤

 

 实现以上需求,开发人员一般情况下可能就是以上 绿 几种选择 

1、有些写在Controllers、有些写在Application

2、都写在Controllers或都写在Application

3、有些写在DAL层、甚至存储过程

 

特别是新手以及那些拿来主义的人,他们不会花更多时间去思考。

分不清各层的职责以及界限,迷信那句:不管黑猫白猫,抓到老鼠就是好猫

最后造成劣质的代码满天飞,到处(无论哪个公司或项目)都充斥着这种随心所欲的代码

分层已经失去意义,因为整个系统在局外人看来已经只有一层,那就是业务逻辑层,上至html、下至数据库存储过程

都充满业务逻辑。联想一下,这只是用户注册而已,还有更加复杂的业务场景还没说出来。不知道最后会怎样

这样的系统已经完完全全一团面条了,后续维护已经与个人技能无关了,就算请一线的NB程序员,想来他也只会说一句,去年买了个表

 

好了,吐槽了一下现状(不管你们同不同意,反正我是不会收回的,哈)

有没有方法解决上面这种窘境呢,当然是有的,比如我就觉得那种蓝色的方案勉强还可以

在UI层解决数据合法性校验,在逻辑层完成功能性问题,分工还算明确,这种方案对付一般的简单业务场景是足够了

 

但是如果业务场景足够复杂,那就不行了,因为这会造成2个明显的问题

1、UI层不够薄,这层只是调用后台的方法而已,按道理校验的事情是无需管的(我说的是cs层的校验,不是js)

    这就像去银行办业务,用户不管钱假不假(因为可能不知道),够不够(可能也不知道,比如他想存一分钱)

    这些银行员工告诉他就可以了

2、业务逻辑不能重用,比如场景1要求注册用户需要完成1-4项,场景2要求完成2-5项,场景3、场景4。。。。

    这就蛋疼了,我们要为每一个场景实现校验到存储的所有过程,代码冗余很大,到处都是相似的代码。

    但是有的开发会说,难道我不能再一个方法里边写if else switch码?那样不就可以兼容其他场景了?

    当然可以那样,这就是那个好猫了,从此以后整个项目就开始堕落,前面一拨人胡乱搞完拍拍屁股走了,

    后边接手的也只能往上边扔更多的扭纹柴了,只到开始改动一个逗号“,”,都会影响其他功能,项目已经彻底走不下去了

    那怎么办?用老板的方法:很简单嘛,项目停掉暂且用着,然后招一批新人从新开发系统,边上边用。把业务都转移到新系统上

    然后新的开发做完系统(可能还没到上线)就拍拍屁股走了,后边的接手的人。。。。然后一个循环的怪圈就开始了。。。

 

 

话题转回来,这么样解决这种窘境,比较合适的业界比较推崇的方法就是加入服务层,来看看加入服务层后的逻辑分层

2、加入服务层后的逻辑分层

 

如何实施呢?我的想法是,UI层只做调用的操作,在构造函数中注入service或直接在Action中调用远程服务方法就好了

当然也可以做一些比如String.IsNullOrEmpty、“value”.ToInt(1);的操作,不过这并不代表服务层就不需要做

服务层还是需要重复校验输入参数是否合法的,所以上边的操作基本没啥卵用,因为服务层从设计角度来说他是不信任任何输入的

不然单元测试都过不去,那服务层到底做些什么呢?可以大概分为以下几个方面

1、解耦UI层与业务逻辑的强耦合

2、较少业务逻辑调用次数

3、层次更加分明,代码简洁

4、部署灵活,以后做集群很方便

如果没有服务层,UI层Controller是怎么写的?大概如下:

RegisterController.cs

 1     public class RegisterController : Controller
 2     {
 3         public RegisterController() { }
 4 
 5         public bool Register()
 6         {
 7             var name = "name";
 8             var password = "password";
 9             var app = new UserApplication();
10 
11             if (!app.CheckName(name)) return false;
12             if (!app.CheckPassword(password)) return false;
13             if (!app.CheckIP()) return false;
14             if (!app.CheckAuthenticationCode()) return false;
15             if (!app.CheckRoleId()) return false;
16             if (!app.CheckOrganizationId()) return false;
17 
18             app.Add(name, password);
19             app.Copy();
20             app.SendMail();
21 
22             return true;
23         }
24     }

UserApplication.cs

 1     public class UserApplication
 2     {
 3         public bool CheckName(string name)
 4         {
 5             return true;
 6         }
 7         public bool CheckPassword(string password)
 8         {
 9             return true;
10         }
11         public bool CheckIP()
12         {
13             return true;
14         }
15         public bool CheckAuthenticationCode()
16         {
17             return true;
18         }
19         public bool CheckRoleId()
20         {
21             return true;
22         }
23         public bool CheckOrganizationId()
24         {
25             return true;
26         }
27         public bool Copy()
28         {
29             return true;
30         }
31         public bool SendMail()
32         {
33             return true;
34         }
35         public bool Add(string name, string password)
36         {
37             return true;
38         }
39     }

如上边代码所示,Controller层太重(很多判断我没写出来,实际情况肯定没有那么简洁的),而且如果是客户端远程部署(不一定是WEB,有可能是C/S、手机等),

那性能肯定很差,因为UI层需要穿透壁垒损耗性能,而且携带大量数据远程传输,多次远程访问等等;而Application也很杂乱,

有些方法比如SendMail这个应该是属于功能性的需求,不是业务性的需求,CheckIp也是,这些不应该写在一起,因为从语义上讲,他们都应该不属于同一个地方

所以要想性能高,Business层要分2层,一层处理业务逻辑(Application),一层处理非业务逻辑(组织相关业务逻辑,即Service),

那就要改了,Controller层和应用层就不能厚,一定要薄,。。

 

3、加入分层后的代码分布

Controller.cs,控制器变了,直接调用WCF,原来是在构造函数中注入Application的

 1         public ActionResult Add(LoginUserCURequest entity)
 2         {
 3             var userClient = new WCFUserService.UserServiceClient();
 4             var addRequest = new LoginUserCURequest()
 5             {
 6                 Id = Guid.NewGuid(),
 7                 LoginName = entity.LoginName,
 8                 Password = entity.Password,
 9                 IsEnabled = entity.IsEnabled,
10                 Ip = entity.Ip,
11                 Phone = entity.Phone,
12                 Mail = entity.Mail,
13                 Roles = entity.Roles
14             };
15             var result = userClient.Add(addRequest);
16 
17             //// 因为是演示,就不出来返回结果了
18             //if (result == "success")
19             //{ }
20 
21             return RedirectToAction("Index");
22         }

DTO也变了很多,加了所以注册需要用到的参数属性

 1     public class LoginUserCURequest
 2     {
 3         /// <summary>Id</summary>    
 4         public Guid Id { get; set; }
 5 
 6         /// <summary>登录账户名</summary>    
 7         public string LoginName { get; set; }
 8 
 9         /// <summary>登录密码</summary>    
10         public string Password { get; set; }
11 
12         /// <summary>是否有效</summary>    
13         public short? IsEnabled { get; set; }
14 
15         /// <summary>Ip</summary>    
16         public string Ip { get; set; }
17 
18         /// <summary>验证码</summary>    
19         public string AuthenticationCode { get; set; }
20 
21         /// <summary>Phone</summary>    
22         public string Phone { get; set; }
23 
24         /// <summary>Mail</summary>    
25         public string Mail { get; set; }
26 
27         /// <summary>所属角色</summary>    
28         public IEnumerable<Guid> Roles { get; set; }
29 
30         public override string ToString()
31         {
32             return string.Format("Id:{0},LoginName:{1},Password:{2},IsEnabled:{3}", 
33                 Id.ToString(), LoginName, Password, IsEnabled.ToString());
34         }
35     }

我们看看WCF的实现

  1     public class UserService : TestBase, IUserService
  2     {
  3         private ILoginUserApplication loginUserApplication;
  4         private IRoleApplication roleApplication;
  5         private LoginUserCURequest loginUserCURequest;
  6 
  7         public UserService()
  8         {
  9             this.loginUserApplication = container.Resolve<ILoginUserApplication>();
 10             this.roleApplication = container.Resolve<IRoleApplication>();
 11         }
 12 
 13         public string Add(LoginUserCURequest entity)
 14         {
 15             this.loginUserCURequest = entity;
 16 
 17             if (!this.CheckPassword())
 18             {
 19                 Logger.Warn("密码不符合规范!");
 20                 return "warn, password error";
 21             }
 22 
 23             if (!this.CheckIP())
 24             {
 25                 Logger.Warn("你所在IP段被禁止注册!");
 26                 return "warn, ip error";
 27             }
 28 
 29             if (!this.CheckAuthenticationCode())
 30             {
 31                 Logger.Warn("你填写的验证码不正确!");
 32                 return "warn, code error";
 33             }
 34 
 35             if (!this.CheckAuthenticationCode())
 36             {
 37                 Logger.Warn("你填写的验证码不正确!");
 38                 return "warn, code error";
 39             }
 40 
 41             //=======================分割线========================
 42 
 43             if (this.loginUserApplication.CheckName(this.loginUserCURequest.LoginName))
 44             {
 45                 Logger.Warn("登录名称已被占用!");
 46                 return "warn, user exists";
 47             }
 48 
 49             if (this.loginUserApplication.CheckPhoneRepeat(this.loginUserCURequest.Phone))
 50             {
 51                 Logger.Warn("手机已经被注册!");
 52                 return "warn, user exists";
 53             }
 54 
 55             if (this.loginUserApplication.CheckMailRepeat(this.loginUserCURequest.Mail))
 56             {
 57                 Logger.Warn("邮箱已经被注册!");
 58                 return "warn, user exists";
 59             }
 60 
 61             bool roleNotExists = false;
 62             foreach (var roleId in this.loginUserCURequest.Roles)
 63             {
 64                 if (this.roleApplication.Get(roleId) == null)
 65                 {
 66                     roleNotExists = true;
 67                     break;
 68                 }
 69             }
 70 
 71             if (roleNotExists)
 72             {
 73                 Logger.Warn("所选角色已经无效!");
 74                 return "warn, role error";
 75             }
 76 
 77             if (this.loginUserApplication.Add(this.loginUserCURequest))
 78             {
 79                 //this.otherLoginUserApplication.Add(this.loginUserCURequest);
 80                 this.SendMail();
 81 
 82                 return "success";
 83             }
 84             else
 85             {
 86                 return "fail";
 87             }
 88         }
 89 
 90         public bool CheckPassword()
 91         {
 92             return true;
 93         }
 94 
 95         public bool CheckIP()
 96         {
 97             return true;
 98         }
 99 
100         public bool CheckAuthenticationCode()
101         {
102             return true;
103         }
104 
105         public bool SendMail()
106         {
107             return true;
108         }
109 
110         public UserList GetAll()
111         {
112             return null;
113         }
114     }

可以看到,分割线上是属于数据合法性校验,之下属于业务逻辑层面的校验

至于LoginUserApplication,之前我们已经实现了,是属于单元(原子)业务层面的功能,只有CRUD

4、看看界面运行效果

 

好了,自此,服务层功能算是介绍完毕了!

 

转载于:https://www.cnblogs.com/lanxiaoke/p/6576177.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于 AJAX 的多架构开发项目,需要考虑以下几个方面: 1.前端技术 前端技术包括 HTML、CSS、JavaScript 等,其 JavaScript 是 AJAX 技术的核心。可以使用 jQuery、Vue.js、React 等前端框架来简化开发。 2.后端技术 后端技术可以选择 PHP、Java、Python 等语言,使用框架例如 SpringMVC、Django、Flask 等来实现数据的处理和存储。 3.AJAX 技术 AJAX 技术可以通过 XMLHttpRequest 对象来实现。通过 AJAX 可以异步地请求后端数据,并将数据插入到前端页面,从而实现无刷新的页面交互效果。 4.多架构架构包括表现、业务逻辑和数据访问。表现负责前端页面的展示和交互,业务逻辑负责业务逻辑的处理,数据访问负责数据的存储和访问。 在多架构,前端页面通过 AJAX 技术向业务逻辑发起请求,业务逻辑处理请求并访问数据访问,最终将处理结果返回给前端页面。 综上所述,基于 AJAX 的多架构开发项目需要掌握前端技术、后端技术、AJAX 技术和多架构的相关知识。 ### 回答2: 基于Ajax的多架构开发项目是一种基于Web的应用程序开发模式。它将应用程序的不同次分离开来,包括展示、业务逻辑和数据访问,并通过Ajax(Asynchronous JavaScript and XML)技术实现前后端之间的数据交互和异步通信。 该多架构开发项目具有以下特点: 1. 分离前后端:通过Ajax技术,前端页面与后端服务器之间的数据交互可以实现无需刷新页面的异步通信,提高用户体验。前端使用JavaScript异步请求数据并将结果动态更新到页面上,后端则负责处理请求并返回所需数据。 2. 提高响应速度:由于Ajax的异步特性,前端可以同时发送多个请求,从而减少页面加载时间和数据传输时间。用户能够迅速地获取数据,同时可以在等待数据的同时进行其他操作。 3. 可重用性和可维护性:将应用程序的不同次分离开来,使得各个次的代码更清晰、更易于维护。开发人员可以专注于各自次的开发,降低代码耦合度,提高代码重用性。 4. 安全性增强:通过Ajax技术,可以减少对敏感数据的暴露,因为只有在用户请求数据时才会传输相关数据,提高了应用程序的安全性。 5. 提供更好的用户体验:通过无需刷新页面的数据更新,用户能够更快地获取所需信息,并能够在页面上进行实时交互,提高了用户的满意度和使用体验。 总之,基于Ajax的多架构开发项目能够提供更好的用户体验、提高响应速度、增强应用程序的安全性,并且具有良好的代码结构和可维护性,是一种值得推荐的开发模式。 ### 回答3: 基于Ajax的多架构开发项目是一种用于构建Web应用程序的技术方案。它将应用程序的不同部分划分为多个次,每个次负责不同的功能和任务,通过Ajax技术进行交互和通信。 这种架构一般由以下几组成: 1. 表示:负责将用户界面展示给用户,并接收用户的交互请求。通常使用HTML、CSS和JavaScript编写,可以实现动态内容的呈现和用户界面的交互。 2. 业务逻辑:负责处理用户请求并进行业务处理。它包含了应用程序的核心逻辑,处理用户的操作和请求,并与数据访问进行交互。这一通常使用服务器端的脚本语言(如PHP、Python或Java)来实现。 3. 数据访问:负责与数据库进行数据的读取、写入和更新操作。通过与数据库进行交互,将数据传递给业务逻辑进行处理,并将处理结果返回给表示。在这一,可以使用SQL语言编写数据库操作语句。 4. 数据库:负责存储应用程序的数据。可以使用关系型数据库(如MySQL、Oracle)或非关系型数据库(如MongoDB)来存储数据。 通过Ajax技术,这些不同次的组件可以实现快速、无刷新的数据交互。在用户与应用程序进行交互时,表示可以通过Ajax技术发送异步请求到业务逻辑,业务逻辑再与数据访问进行交互,最后将结果返回给表示用于页面的更新。 基于Ajax的多架构开发项目具有以下优势: 1. 增强用户体验:通过Ajax技术,实现了快速响应和无刷新的数据更新,提高了用户与应用程序的交互体验。 2. 解耦合性:通过将应用程序的不同部分划分为多个次,实现了各组件之间的解耦合,方便维护和扩展。 3. 可重用性:每个次只负责特定的功能和任务,可以实现组件的重用,提高开发效率。 4. 安全性:通过合理的权限控制和加密机制,保障了数据的安全性。 综上所述,基于Ajax的多架构开发项目可以提升Web应用程序的性能、可维护性和用户体验,并提供了一种灵活可扩展的架构设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值