标签:交互 count nconf pen 重构 设计 target system gen
背景:
在业务频繁迭代的时候,有时候一个菜单页面对应的后台代码会越来越凌乱,一个方法本来就做A、B事情,后面迭代,变成会做A、B、C、D、E事情,且A、B又细分出a1、a2、a3、a4、b1、b2、b3。一个菜单页开始设计代码时,通常写法都较为面向对象,后面经多个人,可能是不同的人迭代后就越来越面向流程。
为什么后面越来越面向流程呢?大约是因为方便吧。如果只是迭代一个小逻辑,一旦要抽出一些通用性的东西,面向对象,写出好扩展的代码,要考虑的情况可能涉及:之前的业务,牵涉到的上下文变量,跟UI的交互(例如弹窗提示报错,询问用户是否继续某操作等等),把之前上线过的东西抽出来放到其他地方又增加了测试的地方等等,太难了。
但代码还能能简单改造一下,这种业务流程像是可以通过责任链设计模式来重构代码。但是这种模式有点隆重感,建好多类,又要抽象类,好像把一个菜单的后台代码复杂化了。但是它的本质,职责层层传递确实又让扩展容易,阅读代码容易。
代码重构过程:
重构前:
private void buttonOld_Click(object sender, EventArgs e) { string fundId = "2323112"; string fundCode = ""; //跨a3、b1使用 string poolID = "";//跨a1、a2使用 string fundName = ""; //A业务 //a1验证 //... poolID = "787908AA"; //... //a2验证 int count = 0; //... if (count == 0) { MessageBox.Show($"{fundId}不在配置数据里;"); LogHelper("...."); return; } //a3验证 //.... if (poolID == "33333") { //... } fundName = "新能源混合"; fundCode = "908898"; //... //B业务 //b1验证 List<string> list = new List<string>(); if (list.Contains(fundCode)) { //... if (MessageBox.Show($"{fundName}确认发送给某某用户", "提示", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } } }
重构后:
using System; using System.Collections.Generic; using System.Data; using System.Windows.Forms; namespace WindowsFormsApp2 { public partial class Form1 : Form { private DataTable ConfigTable; private Dictionary<string, string> LimitDict; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { ConfigTable = new DataTable(); //... LimitDict = new Dictionary<string, string>(); //... } private void buttonNew_Click(object sender, EventArgs e) { string checkErrMesg = ""; string fundID = "2323112"; string fundCode; string fundName; //... CheckBXFund checkBXFund = new CheckBXFund(LogHelper,ConfigTable, LimitDict); if(checkBXFund.Handle(fundID,ref checkErrMesg) == false) { MessageBox.Show(checkErrMesg); return; } fundCode = checkBXFund.OutFundCode; fundName = checkBXFund.OutFundName; //... CheckRisk checkRisk = new CheckRisk(); // if(checkRisk.Handle(fundCode, ref checkErrMesg)==false) { MessageBox.Show(checkErrMesg); return; } //... } private void LogHelper(string Message) { } } /// <summary> /// 假设是整个A业务 /// </summary> internal class CheckBXFund { //应当返回出去的值 1、基金名称 2 基金代码 public string OutFundName; public string OutFundCode; //外面传进来协助验证的一些变量 private DataTable InConfigTable; private Dictionary<string, string> InRepeatDict; private Action<string> LogAction; //有一些操作可能要用外面的窗体实例,例如只有窗体可以Log:this.Log() //方法之间传递的变量,方便跨方法调用 private string PoolID; //参数变量,不必重复获取的一些变量 public CheckBXFund(Action<string> logAction, DataTable dt, Dictionary<string, string> dict) { InConfigTable = dt; InRepeatDict = dict; LogAction = logAction; } public bool Handle(string fundId, ref string errorMessage) { if(IsRepeat(fundId,ref errorMessage) == false) { return false; } if (IsInConfig(fundId, ref errorMessage) == false) { return false; } if (IsCanGetName(fundId, ref errorMessage) == false) { return false; } return true; } /// <summary> /// 假设是a1步骤 /// </summary> /// <param name="fundId"></param> /// <param name="errorMessage"></param> /// <returns></returns> private bool IsRepeat(string fundId,ref string errorMessage) { //... PoolID = "787908AA"; //... return false; } /// <summary> /// 假设是a2步骤 /// </summary> /// <param name="fundId"></param> /// <param name="errorMessage"></param> /// <returns></returns> private bool IsInConfig(string fundId,ref string errorMessage) { int count = 0; //... if (count == 0) { errorMessage = $"{fundId}不在配置数据里;"; LogAction("...."); return false; } return true; } /// <summary> /// 假设是a3步骤 /// </summary> /// <param name="fundId"></param> /// <param name="errMessage"></param> /// <returns></returns> private bool IsCanGetName(string fundId,ref string errMessage) { //.... if (PoolID == "33333") { //... } OutFundName = "新能源混合"; OutFundCode = "908898"; return true; } } /// <summary> /// 假设是整个B业务 /// </summary> internal class CheckRisk { //... public bool Handle(string fundCode,ref string errMessage) { //... return true; } //... } }
总结:在一个类中封装一个业务,职责传递通过一个Handle方法组装,每一个职责就一个方法。跨大业务(大A大B)小业务(小a1、小a2等)的传值通过公共变量传递,和UI的交互通过委托,或者只有窗体实例才能调的方法也通过委托。这一整个类属于菜单的后台代码业务帮助类,和菜单粘性较强。
标签:交互 count nconf pen 重构 设计 target system gen
原文地址:https://www.cnblogs.com/bibi-feiniaoyuan/p/14959967.html