最理想的状态(或者目的)是一个类应该做一件事或者只做一件事。
1.典型代码(Csv文件处理程序)
1 public class CsvFileProcessor 2 { 3 public void Process(string filename) 4 { 5 TextReader tr = new StreamReader(filename); 6 tr.ReadToEnd(); 7 tr.Close(); 8 9 var conn = new SqlConnection("server=(local);integrated security=sspi;database=SRP"); 10 conn.Open(); 11 12 string[] lines = tr.ToString().Split(new string[] {@"\r\l"}, StringSplitOptions.RemoveEmptyEntries); 13 foreach( string line in lines) 14 { 15 string[] columns = line.Split(new string[] {","}, StringSplitOptions.RemoveEmptyEntries); 16 var command = conn.CreateCommand(); 17 command.CommandText = "INSERT INTO People (FirstName, LastName, Email) VALUES (@FirstName, @LastName, @Email)"; 18 command.Parameters.AddWithValue("@FirstName", columns[0]); 19 command.Parameters.AddWithValue("@LastName", columns[1]); 20 command.Parameters.AddWithValue("@Email", columns[2]); 21 command.ExecuteNonQuery(); 22 } 23 conn.Close(); 24 } 25 }
函数 void Process(string filename)使用中用到了太多的类,但是分析其核心功能仅有读取,转换以及存储。
2.由此进行下一步改造
1 public class CsvFileProcessor 2 { 3 public void Process(string filename) 4 { 5 var csvData = ReadCsv(filename); 6 var parsedData = ParseCsv(csvData); 7 StoreCsvData(parsedData); 8 } 9 10 public string ReadCsv(string filename) 11 { 12 TextReader tr = new StreamReader(filename); 13 tr.ReadToEnd(); 14 tr.Close(); 15 return tr.ToString(); 16 } 17 18 public string[] ParseCsv(string csvData) 19 { 20 return csvData.ToString().Split(new string[] { @"\r\l" }, StringSplitOptions.RemoveEmptyEntries); 21 } 22 23 public void StoreCsvData(string[] csvData) 24 { 25 var conn = new SqlConnection("server=(local);integrated security=sspi;database=SRP"); 26 conn.Open(); 27 foreach (string line in csvData) 28 { 29 string[] columns = line.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); 30 var command = conn.CreateCommand(); 31 command.CommandText = "INSERT INTO People (FirstName, LastName, Email) VALUES (@FirstName, @LastName, @Email)"; 32 command.Parameters.AddWithValue("@FirstName", columns[0]); 33 command.Parameters.AddWithValue("@LastName", columns[1]); 34 command.Parameters.AddWithValue("@Email", columns[2]); 35 command.ExecuteNonQuery(); 36 } 37 conn.Close(); 38 } 39 }
现在看上去好多了,但是依旧没有能达到目标(比如:如果文件不是Csv格式,亦或Xml?Json?等等),设计不够牢靠。
3.再次改进
1 public interface IContactDataProvider 2 { 3 string Read(); 4 } 5 public interface IContactParser 6 { 7 IList<ContactDTO> Parse(string contactList); 8 } 9 public interface IContactWriter 10 { 11 void Write(IList<ContactDTO> contactData); 12 } 13 14 public class ContactDTO 15 { 16 public string FirstName { get; set; } 17 public string LastName { get; set; } 18 public string Email { get; set; } 19 } 20 21 public class ContactProcessor 22 { 23 public void Process(IContactDataProvider cdp, IContactParser cp, IContactWriter cw) 24 { 25 var providedData = cdp.Read(); 26 var parsedData = cp.Parse(providedData); 27 cw.Write(parsedData); 28 } 29 } 30 public class CSVContactDataProvider : IContactDataProvider 31 { 32 private readonly string _filename; 33 34 public CSVContactDataProvider(string filename) 35 { 36 _filename = filename; 37 } 38 39 public string Read() 40 { 41 TextReader tr = new StreamReader(_filename); 42 tr.ReadToEnd(); 43 tr.Close(); 44 return tr.ToString(); 45 } 46 } 47 48 public class CSVContactParser : IContactParser 49 { 50 public IList<ContactDTO> Parse(string csvData) 51 { 52 IList<ContactDTO> contacts = new List<ContactDTO>(); 53 string[] lines = csvData.Split(new string[] { @"\r\l" }, StringSplitOptions.RemoveEmptyEntries); 54 foreach (string line in lines) 55 { 56 string[] columns = line.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); 57 var contact = new ContactDTO 58 { 59 FirstName = columns[0], 60 LastName = columns[1], 61 Email = columns[2] 62 }; 63 contacts.Add(contact); 64 } 65 66 return contacts; 67 } 68 } 69 70 public class ADOContactWriter : IContactWriter 71 { 72 public void Write(IList<ContactDTO> contacts) 73 { 74 var conn = new SqlConnection("server=(local);integrated security=sspi;database=SRP"); 75 conn.Open(); 76 foreach (var contact in contacts) 77 { 78 var command = conn.CreateCommand(); 79 command.CommandText = "INSERT INTO People (FirstName, LastName, Email) VALUES (@FirstName, @LastName, @Email)"; 80 command.Parameters.AddWithValue("@FirstName", contact.FirstName); 81 command.Parameters.AddWithValue("@LastName", contact.LastName); 82 command.Parameters.AddWithValue("@Email", contact.Email); 83 command.ExecuteNonQuery(); 84 } 85 conn.Close(); 86 87 } 88 }
至少现在看上去完美了,以后呢???
参考:https://www.dotnetcurry.com/software-gardening/1148/solid-single-responsibility-principle