简单Elixir游戏服设计- 给table增添测试代码

by admin on 2019年1月14日

前日大家的话说三层,首先我们来看一下百度健全对于三层架构的分解:三层架构(3-tier
architecture) 日常意义上的三层架构就是将全方位事情使用细分为:界面层(User
Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data
access
layer)。区分层次的目标即为了“高内聚低耦合”的思维。在软件体系架构设计中,分层式结构是最广泛,也是最紧要的一种结构。微软援引的分层式结构相似分为三层,从下至上各自为:数据访问层、业务逻辑层(又或称为世界层)、表示层。

测试驱动,先simple_table_test.exs 里扩展测试呢。

 

眼前想到的这么多,假诺遗漏后续扩张, 写测试代码比业务代码如故难,

俺们使用三层架构就是为着让所有程序可以越来越便于维护,业务逻辑和展现方法还有数据库操做都可以分离来写,这样开发人士也可以更好的分工。而且容易扩大,假使假若业务要求大增活着要删减某个需求,也易于修改。

便宜是提前想下模块的api接口。

 

像自家如此一晃写那么多测试,其实也尴尬,反馈周期太长,测试驱动就没乐趣了,

下边咱们就来用三层协会实现用户登录:

同时代码调整或者导致测试要双重调整。

率先步我们成立一个解决方案,里面添加三个类库,如下图所示:

(这里只是示例,将来就不这么搞了)

图片 1

除此以外想了下, 像table这样的整装(意思是和谐调用其他模块)模块,

这五个类库分别表示的是业务逻辑层BLL,数据访问层DAL,还有实体Entity,下一步就是添加你需要的变现层,我为了表示领悟直接行使了UI命名。图片 2

为了便利测试,依旧应当分出2种不同风格的api。

创立数据库我就不详细介绍了,只贴出代码就好了

一种是回去 {:ok, table} 和 {:error, reason}的,对接逻辑

1 CREATE TABLE [dbo].[Users]
2 (
3     [Id] INT NOT NULL PRIMARY KEY IDENTITY(1,1), 
4     [Name] NVARCHAR(50) NOT NULL, 
5     [Pass] NVARCHAR(50) NOT NULL
6 )

一种是纯粹操作table的, 方便测试用。

 

上测试代码先,测试肯定会破产

现行大家先来初叶写多少访问层,在数码访问层里,大家第一建立一个救助类SQLServerDALHelper,实现数量连接,代码如下:

图片 3图片 4

图片 5图片 6

 test "开局:少于2个人的时候不能", %{table: table, player1: player1} do
       assert {:error, ErrorMsg.player_not_enough} == table |> SimpleTable.add_seat |> SimpleTable.start(player1)
  end

  test "开局:正在玩中不能", %{table: table, player1: player1} do
    assert {:error, ErrorMsg.can_not_start_when_playing} == table |> SimpleTable.set_playing |> SimpleTable.start(player1)
  end

  test "开局: 准备阶段且人数至少2, 且只有房主能开局", %{table: table, player1: player1, player2: player2} do
       table = table |> SimpleTable.set_creator(player1) 
                     |> SimpleTable.add_seat(player1) 
                     |> SimpleTable.add_seat(player2) 
      assert {:error, ErrorMsg.just_creator_can_start} == table |> SimpleTable.start(player2)
      assert {:ok, new_table} = table |> SimpleTable.start(player1)
      assert table |> SimpleTable.is_playing?
  end

  test "解散:正在玩中不能", %{table: table, player1: player1} do
    assert {:error, ErrorMsg.can_not_dismiss_when_playing} == table |> SimpleTable.set_playing |> SimpleTable.dismiss(player1)
  end

  test "解散:准备阶段只有房主可以", %{table: table, player1: player1, player2: player2} do
     table = table |> SimpleTable.set_creator(player1)
     assert {:error, ErrorMsg.just_creator_can_dismiss} == table |> SimpleTable.dismiss(player2)
     assert {:ok, new_table} = table |> SimpleTable.dismiss(player1) 
     assert new_table |> SimpleTable.is_dismiss?
  end 

  test "加入:正在玩中不能(以后支持?)", %{table: table, player1: player1} do
    assert {:error, ErrorMsg.can_not_join_new_player_when_playing} == table |> SimpleTable.set_playing |> SimpleTable.join(player1)
  end

  test "加入:准备阶段可以", %{table: table, player1: player1} do
    assert {:ok, _new_table} = table |> SimpleTable.join(player1) 
  end

  test "加入: 重复不可以", %{table: table, player1: player1} do
    assert {:error, ErrorMsg.repeated_join} == table |> SimpleTable.add_seat(player1) |> SimpleTable.join(player1)
  end

  test "退出:正在玩中不能(以后支持?)", %{table: table, player1: player1} do
    assert {:error, ErrorMsg.can_not_quit_when_playing} == table |> SimpleTable.set_playing |> SimpleTable.quit(player1)
  end

  test "退出:房主不能(以后支持?)", %{table: table, player1: player1} do
    assert {:error, ErrorMsg.can_not_quit_when_creator} == table |> SimpleTable.set_creator(player1) |> SimpleTable.quit(player1)
  end

  test "测试发牌", %{table: table, player1: player1, player2: player2} do
      cards = [{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}]
      table = table |> SimpleTable.set_cards(cards)
                    |> SimpleTable.add_seat(player1)
                    |> SimpleTable.add_seat(player2)
                    |> SimpleTable.init_deal
      assert [{1, 1}, {1, 2}] == table |> SimpleTable.find_seat(player1) |> Seat.get_cards
      assert [{1, 3}, {1, 4}] == table |> SimpleTable.find_seat(player2) |> Seat.get_cards
  end

  test "补牌: 非玩中不能", %{table: table, player1: player1} do
     assert {:error, ErrorMsg.can_not_deal_when_not_playing} == table |> SimpleTable.deal_one(player1)
  end

  test "补牌: 已经翻牌不能", %{table: table, player1: player1} do
     seat = Seat.init(player1) |> Seat.open
     assert {:error, ErrorMsg.can_not_make_up_when_open} == table |> SimpleTable.update_seat(seat) |> SimpleTable.make_up(player1)
  end

  test "补牌: 已经三张了不能再补", %{table: table, player1: player1} do
     seat = Seat.init(player1) |> Seat.add_cards([1, 2, 3]) 
     assert {:error, ErrorMsg.can_not_make_up_when_full} == table |> SimpleTable.update_seat(seat) |> SimpleTable.make_up(player1)
  end

  test "翻牌: 不是天公牌不能", %{table: table, player1: player1} do
    seat = Seat.init(player1) |> Seat.add_cards([{1, 2}, {1, 5}])
    assert {:error, ErrorMsg.just_tian_gong_can_open} == table |> SimpleTable.update_seat(seat) |> SimpleTable.open(player1)
  end

  test "翻牌: 已经翻过了不能", %{table: table, player1: player1} do
    seat = Seat.init(player1) |> Seat.open
    assert {:error, ErrorMsg.repeated_open} == table |> SimpleTable.update_seat(seat) |> SimpleTable.open(player1)
  end
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Data.SqlClient;
 5 using System.Data;
 6 using System.Text;
 7 
 8 namespace DAL
 9 {
10     public static class SQLServerDALHelper
11     {
12         //integrated security=true 的意思是集成验证,也就是说使用Windows验证的方式去连接到数据库服务器。
13         public static string Consql = @"Data Source=PC-201610212048;Initial Catalog=People_Data_System;Integrated Security=True";
14 
15         public static bool ExecuteNonQuery(string sql)
16         {
17             try
18             {
19                 using (SqlConnection conn = new SqlConnection(Consql))
20                 {
21                     conn.Open();//打开数据库
22 
23                    using( SqlCommand com = new SqlCommand(sql, conn)){
24                     return com.ExecuteNonQuery() > 0;
25                        //通过cmd对象对数据库进行操作,执行非查询
26                    }
27                 }
28             }
29             catch
30             {
31                 throw;
32             }
33         }
34 
35         public static Object ExecuteScalar(string sql)
36         {
37             try
38             {
39                 using (SqlConnection conn = new SqlConnection(Consql))
40                 {
41                     conn.Open();//打开数据库
42 
43                     using( SqlCommand com = new SqlCommand(sql, conn))
44                     {
45                         return com.ExecuteScalar();
46                     }
47                 }
48             }
49             catch
50             {
51                 throw;
52             }
53         }
54 
55         public static SqlDataReader GetDataReader(string sql)
56         {
57             try
58             {
59                 SqlConnection conn = new SqlConnection(Consql);
60 
61                 conn.Open();
62 
63                 using (SqlCommand com = new SqlCommand(sql, conn))
64                 {
65                     return com.ExecuteReader(CommandBehavior.CloseConnection);
66                 }
67             }
68             catch
69             {
70                 throw;
71             }
72         }
73     }
74 }

simple_table_test.exs

View Code

回头大家补上代码,让测试通过。

支援类写完事后就初步写数据库操做事情了,在此间说一下,匡助类微软专程有投机包装的类,可以一直下载应用。数据访问代码如下:这里有简短的增删查方法

实在数据操作的测试和逻辑操作的测试分为2个测试文件会更清晰点,

图片 7图片 8

自身就不做了,仍旧用1个文件。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using Entery;
 5 using System.Data.SqlClient;
 6 using System.Text;
 7 
 8 namespace DAL
 9 {
10      public class PeopleDAL
11     {
12          public bool Insert(People p)
13          {
14              return SQLServerDALHelper.ExecuteNonQuery(
15                  "insert into Users(Name,Pass) values('"
16                 + p.Name
17                 + "','"
18                 + p.Password
19                 + "')");
20          }
21          public bool Delete(People p) {
22              return SQLServerDALHelper.ExecuteNonQuery(
23                  "delete from Users"
24                 + " where Name = '"
25                 + p.Name
26                 + "'"
27                  );
28          }
29 
30          public bool Select(People p) {
31              return SQLServerDALHelper.ExecuteScalar(
32                  "select Pass from Users where Name = '"
33                  + p.Name
34                  + "'").ToString() == p.Password;                
35          }
36          /// <summary>
37          /// 返回数据集
38          /// </summary>
39          /// <returns></returns>
40          public List<People> SelectAll()
41          {
42              return ConvertReaderToTicketList(SQLServerDALHelper.GetDataReader(
43                     "select * from Users"
44                  )
45              );
46          }
47 
48          public static List<People> ConvertReaderToTicketList(SqlDataReader dr)
49          {
50              List<People> ts = new List<People>();
51 
52              if (dr.HasRows)
53              {
54                  while (dr.Read())
55                  {
56                      ts.Add(new People(dr[0].ToString(), dr[1].ToString()));
57                  }
58              }
59 
60              return ts;
61          }
62     }
63 }

 

View Code

我们的数据访问层这就已经写完了,这里究竟也都只是套路而已,精通了套路,所有的东西等于都领悟了。

接下去大家先写实体类,实体类映射的是数量库表,所以实体类里面的习性一定要对应数据库中的表。

图片 9图片 10

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace Entery
 7 {
 8     public class People
 9     {
10         private string name;
11         private string password;
12 
13         public string Name
14         {
15             get { return name; }
16             set { name = value; }
17         }
18 
19         public string Password
20         {
21             get { return password; }
22             set { password = value; }
23         }
24 
25         public People()
26         { 
27         
28         }
29         public People( string name,string password)
30         {
31             this.name = name;
32             this.password = password;
33         }
34     }
35 }

View Code

此处自己添加了一个构造函数,对于可能需要贯彻的职能来说,重载构造函数就多了一种实现模式,所以不管有用没用,先写上加以。

接下去就是工作逻辑层了,那多少个层就需要引用DAL层和Entityc层了,

图片 11图片 12

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using DAL;
 6 using Entery;
 7 
 8 namespace BLL
 9 {
10     /// <summary>
11     /// 这是BLL 业务逻辑层,此层被表现层(UI)调用,同时它自己调用DAL
12     /// </summary>
13     public class PeopleBLL
14     {
15         PeopleDAL dal = new PeopleDAL();
16 
17         public bool Add(People p){
18             //添加一个用户
19             return dal.Insert(p);
20         }
21 
22         public bool Del(People p) {
23             //删除一个用户
24             return dal.Delete(p);
25         }
26 
27         public bool Sel(People p) {
28             //查询用户
29             return dal.Select(p);
30         }
31 
32         public List<People> ShowAll()
33         {
34             return dal.SelectAll();
35         }
36     }
37 }

View Code

咱俩在写完业务逻辑层之后将要考虑表现层的题目了,为了将增删改查都在一个页面上显现出来,WinForm这样设计

图片 13所需控件,lable textbox
button dataGridView。

前日就是考虑实现的时候了。首先写注册,

图片 14图片 15

 1      private void button2_Click(object sender, EventArgs e)
 2         {
 3             try
 4             {
 5                 //新建一个类,这里使用无参的构造函数,方便以后反射
 6                 People p = new People();
 7 
 8                 //为它的属性赋值
 9                 p.Name = textBox1.Text.ToString();
10                 p.Password = textBox2.Text.ToString();
11 
12                 //调用bll的添加业务
13                 string message = bll.Add(p) ? "添加成功" : "添加失败";
14 
15                 MessageBox.Show(message);
16             }
17             catch
18             {
19                 throw;
20             }
21         }

View Code

首先注册一个admin
密码也为admin,用来测试登陆和删除,然后实现dataGridView呈现所有数据。

图片 16图片 17

 1 这里先自定义一个shows()方法,然后在Form_Load里调用shows()方法 
 2 private void shows()
 3         {
 4             try
 5             {
 6                 dataGridView1.DataSource = bll.ShowAll();
 7             }
 8             catch {
 9                 MessageBox.Show("链接数据库出错");
10             }
11         }

View Code

现今注册一个用户然后看看展现的效劳。

图片 18图片 19为何dataGridView会呈现那个样子呢?为何添加的中文用户名会出现??那一个符号呢?大家有没有相逢过这种场馆

率先先表达首个问题,我们的Name突显的确实ID编号,这么些就是大家的实体类缺失Id那个特性,不过在查询的时候查询的紧缺所有的性能,这样子就应运而生了这些展现没有对齐的景色,怎么解决吗,多个法子,第一改动查询条件,只询问Name和Pass,第二大家抬高实体ID,我们就用第两种办法吗。

修改实体代码如下

 1 public string Id
 2         {
 3             get;
 4             set;
 5         }
 6 public People( string id,string name,string password)
 7         {
 8             this.id = id;
 9             this.name = name;
10             this.password = password;
11         }

只这样修改如故不行的,因为我们在查询格局上还有错误,接着在改动一下DAL层

 1   public static List<People> ConvertReaderToTicketList(SqlDataReader dr)
 2          {
 3              List<People> ts = new List<People>();
 4 
 5              if (dr.HasRows)
 6              {
 7                  while (dr.Read())
 8                  {
 9                      ts.Add(new People(dr[0].ToString(), dr[1].ToString(),dr[2].ToString()));
10                  }
11              }
12 
13              return ts;
14          }

这么第一个冒出的题目就缓解了,下来我们的话第二个问题,这一个题材是因为数量格式问题,大家string格式对应的是Varchar()但是我们用的是Nvarchar(),所以我们理应在插入数据这块添加一个N,修改代码如下:

1  public bool Insert(People p)
2          {
3              return SQLServerDALHelper.ExecuteNonQuery(
4                  "insert into Users(Name,Pass) values(N'"
5                 + p.Name
6                 + "',N'"
7                 + p.Password
8                 + "')");
9          }

当今安插数据格式问题也化解了。图片 20

接着我们初始要落实登陆问题了。代码如下:

图片 21图片 22

 1  private void button1_Click(object sender, EventArgs e)
 2         {
 3             try
 4             {
 5                 //新建一个类,这里使用无参的构造函数,方便以后反射
 6                 People p = new People();
 7 
 8                 //为它的属性赋值
 9                 p.Name = textBox1.Text.ToString();
10                 p.Password = textBox2.Text.ToString();
11                 
12                 //调用bll的添加业务
13                 string message = bll.Sel(p) ? "登陆成功" : "登陆失败";
14 
15                 MessageBox.Show(message);
16             }
17             catch
18             {
19                 throw;
20                 //如果出错,可能是数据转换出错或者数据库里已经存在相同的票号
21                // MessageBox.Show("输入数据形式错误,或主键重复");
22             }
23         }

View Code

登陆代码实现之后就是剔除数据的落实了,

图片 23图片 24

 1 private void button3_Click(object sender, EventArgs e)
 2         {
 3             try
 4             {
 5                 //新建一个类,这里使用无参的构造函数,方便以后反射
 6                 People p = new People();
 7 
 8                 //为它的属性赋值
 9                 p.Name = textBox1.Text.ToString();
10 
11                 //调用bll的添加业务
12                 string message = bll.Del(p) ? "删除成功" : "删除失败";
13 
14                 MessageBox.Show(message);
15             }
16             catch
17             {
18                 throw;
19             }
20         }

View Code

前几日我们所急需的增删查问题都早就落实了,然则还有题目,什么问题吗,大家在运作程序的时候会发先dataGridView显示数据在进行增删之后都不举办刷新,所以在推行这六个操做的时候事情执行了而是多少却惊惶失措刷新到dataGridView控件中,我们应有用什么措施解决吗?大家不是写了一个shows()方法用来展现数据吧,我们只要在急需多少刷新的地方调用这一个方法就行了,实现很简短,我就不具体改了,我们下来自己要促成的改一下就好了。先天的内容早已写完了,希望我们援助,文中有不当希望我们可以指出来,让自家上学改良。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图