SRP

时刻提醒自己是否这个类或者方法符合SRP,我们需不需要把其分成小份的?

single responsibility principle states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

View Code
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace ConsoleApplication4
 8 {
 9     class Person
10     {
11         public int Id { get; private set; }
12         public string Name { get; private set; } //constracter给property赋值,比较下面
13         public Person(int id, string name)
14         {
15             Id = id;
16             Name = name;
17         }
18     }
19     
20     class People
21     {
22         private Dictionary<int, Person> _people;
23         public People() //constracter给filed赋值
24         {
25             _people = new Dictionary<int,Person>();
26         }
27         public void AddPerson(Person person)
28         {
29             _people.Add(person.Id, person);
30         }
31         public Person GetPersonById(int id)
32         {
33             return _people[id]; //如果希望throw exception用这个
34 
35          /* 如果不希望找不到key后throw exception,用这个这不到的话返回null,person可以是null
36           * 
37             Person person;
38             if (_people.TryGetValue(id, out person))
39             {
40                 return person;
41             }
42             return null;
43           */
44         }
45         public void DisplayPeople()
46         {
47             foreach (var person in _people)
48             {
49                 Console.WriteLine("{0} - {1}", person.Key, person.Value.Name);
50             }
51         }
52     }
53 
54     class Program
55     {
56         static void Main(string[] args)
57         {
58             var people = new People();
59              people.AddPerson(new Person(423, "Nelson"));
60              people.AddPerson(new Person(233, "shawn"));
61              people.AddPerson(new Person(443, "chris"));
62              people.AddPerson(new Person(133, "rebecca"));
63              people.AddPerson(new Person(533, "mandy"));
64              people.DisplayPeople();
65              Console.Write("Selected People:");
66              var selectedId = int.Parse(Console.ReadLine());
67              var person = people.GetPersonById(selectedId);
68              Console.WriteLine("You selected {0}", person.Name);
69              Console.ReadLine();
70         }
71         
72     }
73 }

上面例子的people类有两个功能,第一个存储person的信息,第二个显示每一个person,不符合SRP,一步步的把上面的code拆分,最后得到下面的code

View Code
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace ConsoleApplication4
 8 {
 9     class Person
10     {
11         public int Id { get; private set; }
12         public string Name { get; private set; }
13         public Person(int id, string name)
14         {
15             Id = id;
16             Name = name;
17         }
18     }
19     
20     class Peoples
21     {
22         public Dictionary<int, Person> People { get; private set; } //其实这样不是很好,因为外界通过62行
23         //改成public的property向外透露,private
24         //的原因是外界不能直接set,全部由内部的constractor来set
25         public Peoples() 
26         {
27             People = new Dictionary<int, Person>();
28         }
29         public void AddPerson(Person person)
30         {
31             People.Add(person.Id, person);
32         }
33         public Person GetPersonById(int id)
34         {
35             return People[id]; 
36         }
37     }
38     
39     class PeopleView    //好处程序用同一个People类的Data,但不同的PeopleView(like unity, wpf)
40     {
41         private Peoples _people;
42         public PeopleView (Peoples people)
43         {
44             _people = people;
45         }
46         public void DisplayPeople()
47         {
48             foreach (var person in _people.People)
49             {
50                 Console.WriteLine("{0} - {1}", person.Key, person.Value.Name);
51             }
52         }
53         public Person SelectedPerson()
54         {
55             DisplayPeople();
56             Console.Write("Selected People:");
57             var selectedId = int.Parse(Console.ReadLine());
58             return _people.GetPersonById(selectedId);
59         }
60         public void DisplayPerson(Person person)
61         {
62             Console.WriteLine("Person: {0} is named {1}", person.Id, person.Name);
63         }
64     }
65 
66 
67     class Program
68     {
69         static void Main(string[] args)
70         {
71             
72             var people = new Peoples();
73             //people.People.Add(333, "hahaha");
74             var view = new PeopleView(people); //习惯使用var而不是下面
75             //PeopleView view = new PeopleView(people);
76              people.AddPerson(new Person(423, "Nelson"));
77              people.AddPerson(new Person(233, "shawn"));
78              people.AddPerson(new Person(443, "chris"));
79              people.AddPerson(new Person(133, "rebecca"));
80              people.AddPerson(new Person(533, "mandy"));
81              var selectedPerson = view.SelectedPerson();
82              view.DisplayPerson(selectedPerson);
83              
84              Console.ReadLine();
85         }
86         
87     }
88 }

 继续我们可以换成interface,这样更通用,可以有多种不同view的方法实现

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 
  7 namespace ConsoleApplication5
  8 {
  9     class Person
 10     {
 11         public int Id { get; private set; }
 12         public string Name { get; private set; }
 13         public Person(int id, string name)
 14         {
 15             Id = id;
 16             Name = name;
 17         }
 18     }
 19     class People
 20     {
 21         public Dictionary<int, Person> PeopleCollection { get; private set; }
 22         //计算是private setter也不是最好的implementation
 23         public People()
 24         {
 25             PeopleCollection = new Dictionary<int, Person>();
 26         }
 27         public void AddPerson(Person person)
 28         {
 29             PeopleCollection.Add(person.Id, person);
 30         }
 31         public Person GetPersonById(int id)
 32         {
 33             return PeopleCollection[id];
 34         }
 35         
 36     }
 37     interface IPeopleView
 38     {
 39         void DisplayPeople();
 40         Person SelectedPerson();
 41         void DisplayPerson(Person person);
 42     }
 43     class ConsolePeopleView:IPeopleView
 44     {
 45         private People _people;
 46         public ConsolePeopleView(People people)
 47         {
 48             _people = people;
 49         }
 50         public void DisplayPeople()
 51         {
 52             foreach (var person in _people.PeopleCollection)
 53             {
 54                 Console.WriteLine("{0} - {1}", person.Key, person.Value.Name);
 55             }
 56         }
 57         public Person SelectedPerson()
 58         {
 59             DisplayPeople();
 60             Console.Write("Select People: ");
 61             var selectedId = int.Parse(Console.ReadLine());
 62             return _people.GetPersonById(selectedId);
 63         }
 64         public void DisplayPerson(Person person)
 65         {
 66             Console.WriteLine("Person {1} name is {0}", person.Id, person.Name);
 67         }
 68     }
 69     /*class InterfaceGUIPeopleView : IPeopleView
 70     {
 71         ......
 72     }
 73     class UnityGUIPeopleView : IPeopleView
 74      {
 75      ......
 76 
 77      }
 78     */
 79     class Program
 80     {
 81         static void RunProgram(People model, IPeopleView view)
 82         //Runprogramm不知道它会得到什么view,
 83         //只要是继承自IPeopleView的view都可以
 84         //interface的好处,进来任何的view都有同样的逻辑,选择一个peoson,display它
 85         {
 86             
 87             model.AddPerson(new Person(123, "Shawn"));
 88             model.AddPerson(new Person(927, "Baba"));
 89             model.AddPerson(new Person(453, "Tutu"));
 90             
 91             var selectedPerson = view.SelectedPerson();
 92             view.DisplayPerson(selectedPerson);
 93         }
 94 
 95         static void Main(string[] args)
 96             
 97         {
 98             var people = new People();
 99             var view = new ConsolePeopleView(people);
100 
101             RunProgram(people, view);
102             Console.ReadLine();
103         }
104     }
105 }

这部分代码更像是Unit Test,因为simulate了用户的输入,但是其实我们程序应该不知道用户输入的是什么。

我们可以日后改成:

 

 

考虑这个是否break SRP?

其实没有,因为每一个类执行了自己被要求做的事情,虽然ThinggyRepository里的Add方法访问了DataBase。就想是个manager一样,我要这件事被做!!

 

 

posted @ 2013-05-08 15:28  若愚Shawn  阅读(599)  评论(0编辑  收藏  举报