美文网首页
{C#}程序分层

{C#}程序分层

作者: 码农猫爸 | 来源:发表于2021-04-10 17:03 被阅读0次

    目的

    • 层可以理解为同类职责的集合,使程序结构更清晰。

    实现

    • 程序可简单分为三层,分别为

      • 表示层(User Interface),简称UI(又称View)。

      提供用户界面,如文本框、按钮和提示框等。
      响应用户操作,如文本输入,鼠标点击等。

      • 业务逻辑层(Business Logic Layer),简称BLL或(又称Presenter)。

      处理UI层请求,并返回处理结果,即UI单向调用BLL。
      依赖注入时,UI单向调用DAL作参数至BLL。
      单元测试的重点。

      • 数据访问层(Data Access Layer),简称DAL(又称Data)。

      向BLL层提供持久化数据,即BLL单向调用DAL。
      操作数据库,如更新(update)、插入(insert)、删除(delete)和查询(select)等。
      操作文件,如读取和写入JSON。

      • 模型层(Model),三层共用的数据类型。

      如接口的定义。
      数据类定义,作为参数。

    参考代码(实测OK)

    • 表示层
    using System.Windows.Forms;
    using AP = App.Presenters; // 空间别名AP
    using AD = App.Data;
    
    namespace App.Views
    {
        public partial class Login : Form
        {
            private AP.Login presenter; // 别名.重名类Login,取名简单了
    
            public Login()
            {
                InitializeComponent();
    
                SetPresenter();
            }
    
            private void SetPresenter()
            {
                // 表示层(UI)单向调用逻辑层(BLL)和数据访问层(DAL)
                var user = new AD.User(1);
                presenter = new AP.Login(user); // 控制反转(IOC),方便单元测试
            }
        }
    }
    
    
    • 逻辑层
    using App.Models;
    using System.Diagnostics;
    
    namespace App.Presenters
    {
        public class Login
        {
            private readonly IUser user;
    
            public Login(IUser user)
            {
                Debug.Assert(user != null);
    
                this.user = user;
            }
    
            public bool Validate(string inputPassword)
            {
                var info = user.GetInfo();
    
                return inputPassword == info.Password;
            }
        }
    }
    
    • 数据层
    using App.Models;
    using System.Diagnostics;
    
    namespace App.Data
    {
        public class User : IUser
        {
            private readonly int userID;
    
            public User(int userID)
            {
                Debug.Assert(userID > 0); // 检查参数有效性
    
                this.userID = userID;
            }
    
            // 实际结果来自数据库,演示采用假定值
            public UserInfo GetInfo()
                => new UserInfo
                {
                    Name = "张三",
                    Password = "1234",
                };
        }
    }
    
    • 模型层
    namespace App.Models
    {
        public class UserInfo
        {
            public string Name { get; set; }
            public string Password { get; set; }
        }
    }
    
    namespace App.Models
    {
        public interface IUser
        {
            UserInfo GetInfo();
        }
    }
    
    • 单元测试
    using App.Models;
    using App.Presenters;
    using Moq; // 替身工具
    using Xunit; // 单元测试工具
    
    namespace AppTests
    {
        public class LoginTests
        {
            private Mock<IUser> user = new Mock<IUser>(); // 替身类,免构造器传参
            private Login testee; // 被测类
    
            public LoginTests()
            {
                user.Setup(x => x.GetInfo()).Returns(
                    new UserInfo
                    {
                        Name = "张三",
                        Password = "1234",
                    }); // 替身函数
    
                testee = new Login(user.Object);
            }
    
            [Theory(DisplayName ="登录检查")]
            [InlineData("4321", false)]
            [InlineData("1234", true)]
            public void Validate_ReturnsTrue(string input, bool expected)
            {
                bool actual = testee.Validate(input);
    
                Assert.Equal(expected, actual);
            }
        }
    }
    
    资源管理器.jpg

    相关文章

      网友评论

          本文标题:{C#}程序分层

          本文链接:https://www.haomeiwen.com/subject/jdtnkltx.html