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一样,我要这件事被做!!