博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
架构,改善程序复用性的设计~第三讲 实现一种功能的代码只能出现在一处(续)...
阅读量:5864 次
发布时间:2019-06-19

本文共 8019 字,大约阅读时间需要 26 分钟。

原文:

在写完这篇文章后,得到了园友的反馈,说这种简单的业务逻辑还可以,但业务比较复杂时,根据就没法用这种方法。

针对这个问题,我觉得有必要再写一个续集了,呵呵!

上回说的主要核心内容是将公用的部分从一个方法中提取出来,生成一个新的方法,这个重构中叫做“提取到方法”

,另外一个核心内容就是方法的”单一职责“,即一个方法干一件事,将出现复杂事件时,将多个方法进行组合调用即可

这回主要说一个重构中的提取,其实不仅方法可以被提取,类,及整个项目也可以被提取,只要他们有被提取的必要!

一个例子:对于一个数据实体操作的基类,它包括了其它所有实体类共有的属性(DB)和方法(SubmitChanges),这可以理解了”提取到类“,当然这也是类的继承及面向对象的一个例子。

1      ///  2     /// LINQ数据库操作基类 3     ///  4     public abstract class RepositoryBase 5     { 6         public RepositoryBase(DataContext db) 7         { 8             DB = db; 9         }10        protected System.Data.Linq.DataContext DB { get; private set; }11 12         #region DBContext SubmitChanges13         /// 14         /// XXB默认提交【重写时候可能需要写入自定义的类似约束的逻辑】15         /// 16         protected virtual void SubmitChanges()17         {18             ChangeSet cSet = DB.GetChangeSet();19             if (cSet.Inserts.Count > 020                 || cSet.Updates.Count > 021                 || cSet.Deletes.Count > 0)22             {23                 try24                 {25                     DB.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);26                 }27                 catch (System.Data.Linq.ChangeConflictException ex)28                 {29                     foreach (System.Data.Linq.ObjectChangeConflict occ in DB.ChangeConflicts)30                     {31                         // 使用当前数据库中的值,覆盖Linq缓存中实体对象的值  32                         occ.Resolve(System.Data.Linq.RefreshMode.OverwriteCurrentValues);33                         // 使用Linq缓存中实体对象的值,覆盖当前数据库中的值  34                         occ.Resolve(System.Data.Linq.RefreshMode.KeepCurrentValues);35                         // 只更新实体对象中改变的字段的值,其他的保留不变  36                         occ.Resolve(System.Data.Linq.RefreshMode.KeepChanges);37                     }38                     DB.SubmitChanges();39                 }40             }41         }42 43         #endregion44      }

还有一种更大程序上的提取,即”提取到项目“,就是说,它的整个项目都是其它项目公用的部分,所有把整个项目抽象出来

Entity.Commons这个项目是对所有解决方案的所有实体层进行的抽象,它里面有对实体的分页,实体参数组织,实体消息返回及实体统一验证等功能,都在Entity.Commons里实现

EntityBase.cs代码如下:

View Code
1     ///   2     /// 实体基类,与linq to sql数据映射对应  3     ///   4     [Serializable]  5     public abstract class EntityBase /*: INotifyPropertyChanging, INotifyPropertyChanged*/  6     {  7   8         public EntityBase()  9         { 10             this.IsRealDeleted = true; 11         } 12         #region 实体相关 13         ///  14         /// 实体主键 15         /// 在子类中对它赋值,在其它类中可以访问到这个主键属性 16         ///  17         public abstract object[] PrimaryKey { get; } 18         ///  19         /// 是否执行真删除,默认为true,如果设为false,则更新实体的status字段 20         ///  21         public virtual bool IsRealDeleted { get; protected set; } 22         ///  23         /// 记录修改的列信息 24         /// 子类可以根据需要,去复写记录数据的方式 25         ///  26         ///  27         ///  28         protected virtual void PropertyChangedEvent(object sender, PropertyChangedEventArgs e) 29         { 30             #region 添加修改字段记录 31             // VLog.IVLog log = new VLog.SqlVLog(); 32             // log.Write(string.Format("被修改的字段{0}", e.PropertyName)); 33             #endregion 34             #region 记录修改的字段和修改成的值 35             Type t = this.GetType(); 36             PropertyInfo pi = t.GetProperty(e.PropertyName); 37             object value = pi.GetValue(this, null); 38             this.OnPropertyChanged(e.PropertyName, value); 39             #endregion 40  41         } 42         #endregion 43  44         #region 实体验证 45  46         ///  47         /// 验证的字段名集合,为NULL表示验证所有字段 48         ///  49         public string[] ValidFields { get; set; } 50  51         ///  52         /// 数据验证(是否成功) 53         /// 虚属性,子类可以根据自己的逻辑去复写 54         ///  55         public virtual bool IsValid { get { return this.GetRuleViolations().Count() == 0; } } 56         ///  57         /// 获取验证失败的信息枚举,默认提供了非空验证 58         /// 它使用了简单的迭代器,如果GetRuleViolations有错误则返回迭代列表 59         ///   60         /// 
61 public virtual IEnumerable
GetRuleViolations() 62 { 63 PropertyInfo[] propertyInfo = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 64 if (ValidFields != null) propertyInfo = propertyInfo.Where(i => ValidFields.Contains(i.Name)).ToArray(); 65 foreach (var i in propertyInfo) 66 { 67 if (i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false) != null 68 && i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false).Count() > 0 69 && !((System.Data.Linq.Mapping.ColumnAttribute)i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false)[0]).CanBeNull 70 && !((System.Data.Linq.Mapping.ColumnAttribute)i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false)[0]).IsPrimaryKey) 71 if (i.GetValue(this, null) == null || string.IsNullOrEmpty(i.GetValue(this, null).ToString())) 72 yield return new RuleViolation("*", i.Name); 73 } 74 } 75 #endregion 76 77 #region 重写linq to sql的一些东西 78 79 #region INotifyPropertyChanged and INotifyPropertyChanging Members 80 81 public event PropertyChangedEventHandler BasePropertyChanged; 82 public event PropertyChangingEventHandler BasePropertyChanging; 83 protected virtual void OnPropertyChanging(String propertyName) 84 { 85 if ((this.BasePropertyChanging != null)) 86 { 87 this.BasePropertyChanging(this, new PropertyChangingEventArgs(propertyName)); 88 } 89 } 90 protected virtual void OnPropertyChanged(String propertyName, object newValue) 91 { 92 if ((this.BasePropertyChanged != null)) 93 { 94 this.BasePropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 95 } 96 97 if (_changeList == null) 98 return; 99 100 if (_changeList.ContainsKey(propertyName))101 {102 _changeList.Remove(propertyName);103 }104 _changeList.Add(propertyName, newValue);105 }106 protected bool IsPropertyChanged(string name)107 {108 return _changeList != null && _changeList.ContainsKey(name);109 }110 #endregion111 112 #region Change tracking113 114 private Dictionary
_changeList;115 116 public Dictionary
GetChanges()117 {118 return _changeList;119 }120 121 private void StartTrackChanges()122 {123 if (_changeList != null)124 {125 throw new InvalidOperationException("This object is already tracking changes");126 }127 _changeList = new Dictionary
();128 }129 130 private bool _IsAlreadySaved = false;131 132 public bool IsAlreadySaved()133 {134 return _IsAlreadySaved;135 }136 ///
137 /// 保存实体138 /// 139 public void MarkEntitySaved()140 {141 _IsAlreadySaved = true;142 }143 ///
144 /// 实体初始化,开始跟踪实体的变化 145 /// 146 public virtual void Initialization()147 {148 this.StartTrackChanges();149 }150 151 #endregion152 153 #endregion154 }155 #region 子类更新需要实现它的分部方法,内容如下156 //partial void OnCreated()157 // {158 // base.IsRealDeleted = false;//假删除159 // base.Initialization();//基类的某些属性初始化160 // this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(base.PropertyChangedEvent);//初始实体时,先订阅列修改的事件161 // }162 #endregion

通过这篇文章,我们知道了,对于代码重构,不仅仅只对于方法而言,对于重构,也不仅仅只对一个项目而言,它可能是项目与项目之间的重构。

转载地址:http://dgunx.baihongyu.com/

你可能感兴趣的文章
Mesos DRF算法的论文阅读
查看>>
MPLS LDP报文格式
查看>>
4..21学习内容总结
查看>>
基于Elasticsearch+Fluentd+Kibana的日志收集分析系统
查看>>
大数据分析在新型智慧能源建设中的应用
查看>>
netty源码分析之服务端启动
查看>>
Get了这个外挂级神器,一个小时的工作我竟然十分钟就做完了
查看>>
web.xml里<filter-mapping>中的<dispatcher>
查看>>
101.使用 js 选择 单选框 复选框 下拉框
查看>>
问答推广怎么做有效果?关于问答推广的小技巧分享
查看>>
JBoss应用服务器监控
查看>>
常用excel技巧
查看>>
2019/1/14 Linux基础学习
查看>>
分离式部署LNMP架构并实现项目上线
查看>>
请求内部转发与重定向区别
查看>>
分析企业上云的办法及意义
查看>>
CAD快速看图如何打印图纸的部分内容?
查看>>
华为路由器 静态路由
查看>>
如何打造专属直播平台
查看>>
discuz 提供管理员权限
查看>>