zoukankan      html  css  js  c++  java
  • 重构指导之一

    一:频繁出现的代码可以使用委托类型的 AOP

    类似以下代码在控制器中(在Domain中也有若干)重复出现:

    try
    {
        if (!string.IsNullOrEmpty(categoryId))
        {
            var model = new ExerciseCategory();
            model.ParentId = parentId;
            this._exerciseCategoryDal.Update(model);
        }
    }
    catch
    {
        return 0;
    }

    return 1;

    可重构为:

    return ExceptionWrapper.ParseInt(() =>
        {
            if (!string.IsNullOrEmpty(categoryId))
            {
                var model = new ExerciseCategory();
                model.ParentId = parentId;
                this._exerciseCategoryDal.Update(model);
            }
        });

    二:控制器不应放太多逻辑

    一段典型代码如下:

    public JsonResult GetAuditProcess(string id, int type, string isComplex)
            {
                var dataTypeEnum = (DataTypeEnum)type;
                int dataAuditState;
                CategoryAudit categoryAudit;
                switch (dataTypeEnum)
                {
                    case DataTypeEnum.Organization:
                        var org = this._organizationDal.FindOne(new Organization { Id = id });
                        return this.Json(org, JsonRequestBehavior.AllowGet);
                    case DataTypeEnum.Project:
                        var category = new DAL.Project.ProjectCategoryDal().FindOne(new ProjectCategory { Id = id });
                        dataAuditState = new YHBJ.Domain.Project.ProjectCategoryBll().GetDataAuditState(category);
                        categoryAudit = new CategoryAudit
                                            {
                                                DataAuditState = dataAuditState,
                                                AuditProcesses = category.AuditProcesses
                                            };
                        return this.Json(categoryAudit, JsonRequestBehavior.AllowGet);

                        ……省略

                }

                return null;
            }

    这个方法存在几个问题:

    1:控制器方法内有太多逻辑代码,应重构到 Domain 中去;

    2:swtich 中返回的实体不统一,第一个返回的是 organization,其余都是 categoryAudit,这导致无法提炼出方法;

    3:虽然有 “尽早返回” 这个原则,但该原则不适用 swtich;

    应重构为:

    public JsonResult GetAuditProcess(string id, int type, string isComplex)
    {
        var dataTypeEnum = (DataTypeEnum)type;
        CategoryAudit categoryAudit = this._auditProcessor.GetCategoryAudit(id, dataTypeEnum);
        return this.Json(categoryAudit, JsonRequestBehavior.AllowGet);
    }

    其中 ._auditProcessor 是类型 AuditProcessor,被放置到了 Domain 中:

    public class AuditProcessor
    {
        private readonly OrganizationDal _organizationDal = new OrganizationDal();

        public CategoryAudit GetCategoryAudit(string id, DataTypeEnum dataTypeEnum)
        {
            CategoryAudit categoryAudit = null;
            int dataAuditState;
            switch (dataTypeEnum)
            {
                case DataTypeEnum.Organization:
                    var org = this._organizationDal.FindOne(new Organization { Id = id });
                    categoryAudit = new CategoryAudit
                                        {
                                            DataAuditState = (int)org.AuditState,
                                            AuditProcesses = org.AuditProcesses
                                        };
                    break;
                case DataTypeEnum.Project:
                    var category = new DAL.Project.ProjectCategoryDal().FindOne(new ProjectCategory { Id = id });
                    dataAuditState = new YHBJ.Domain.Project.ProjectCategoryBll().GetDataAuditState(category);
                    categoryAudit = new CategoryAudit
                                        {
                                            DataAuditState = dataAuditState,
                                            AuditProcesses = category.AuditProcesses
                                        };
                    break;

                    ……省略

            }

            return categoryAudit;
        }
    }

    public class CategoryAudit
    {
        public int DataAuditState { get; set; }

        public List<AuditProcess> AuditProcesses = new List<AuditProcess>();
    }

    三:二转手代码不应该出现

    除非有明确的规定,比如:在控制中不应该出现 Dal,否则,象下面的二转手代码不应该出现:

    public bool Add(ProjectPropSetting projectPropSetting)
    {
        try
        {
            this._projectPropSettingDal.Insert(projectPropSetting);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    应该直接在控制器重调用 Dal 就可以了。备注:如果带有其它复杂逻辑或者包装了事务等,则应该创建业务逻辑层。

    四:不必要的异常包装和处理

    上面的代码中还出现了不不要的异常包装和处理,一般的异常应该容许抛出到控制器中,由控制器中的 AOP 代码(见文中一处)进行处理。备注:除非某个特定异常我们就是要处理。

    五:不必要的控制器返回信息

    类似如下代码没有必要:

    public string SaveProjectProp(string isEdit, string projectProp, string id)
    {
        var prop = new JavaScriptSerializer().Deserialize<ProjectPropSetting>(projectProp);
        prop.Id = Guid.NewGuid().ToString().Replace("-", string.Empty);
        var flag = new YHBJ.Domain.Project.ProjectPropSettingBll().Add(prop);
        if (flag)
        {
            return "添加成功!";
        }
       
        return "添加失败!";
    }

    可以通过 AOP 包装返回信息,或者甚至是不包装。返回信息一般也是一个 flag,如 0和1,或者 true和false,然后由前台进行判断并处理成友好的信息。

    六:事务出现的位置

    事务不应该出现在控制器中,如果需要用到事务,它应该在 Domain 或者 Dal 或者直接在 sql 中。出现在 Domain 中的事务,我包装了一下,你可以像下面这样来使用:

    TransactionProcessor.Commit(() =>
    {
        foreach (var item in ls)
        {
            this._xxxDal.Delete(new LearnCard { Id = item.Id });
        }
    });

    TransactionProcessor 被定义在了 Utility 中,感兴趣者可查看其源码。

    七:避免出现魔术字

    在代码中不应该出现魔术字,可以使用枚举或者 const 字段来代替它们。如:

    this.ViewBag.CredentialsType = prarm.FindAll(paramenter => paramenter.paramenterTypeId == 2004);
    this.ViewBag.Nationality = prarm.FindAll(paramenter => paramenter.paramenterTypeId == 3);
    this.ViewBag.Politics = prarm.FindAll(paramenter => paramenter.paramenterTypeId == 14);
    this.ViewBag.Education = prarm.FindAll(paramenter => paramenter.paramenterTypeId == 6);
    this.ViewBag.Degree = prarm.FindAll(paramenter => paramenter.paramenterTypeId == 16);

    应该修改为:

    this.ViewBag.CredentialsType = prarm.FindAll(paramenter => paramenter.paramenterTypeId == (int)MagicSystemParamenter.CardType);
    this.ViewBag.Nationality = prarm.FindAll(paramenter => paramenter.paramenterTypeId == (int)MagicSystemParamenter.Folk);
    this.ViewBag.Politics = prarm.FindAll(paramenter => paramenter.paramenterTypeId == (int)MagicSystemParamenter.Politics);
    this.ViewBag.Education = prarm.FindAll(paramenter => paramenter.paramenterTypeId == (int)MagicSystemParamenter.STPM);
    this.ViewBag.Degree = prarm.FindAll(paramenter => paramenter.paramenterTypeId == (int)MagicSystemParamenter.Degree);

    Model 的 Systems 文件夹下存在一个 MagicNumber 文件,专门用于防止你可能觉得无处归类的魔术字。

    八:善用匿名类型

    如果一个类型只是在控制器中用到,则可以使用匿名类型,如:

                    return this.Json(new { e = -1, msg = "卡号错误" });

    九:避免出现重复代码

    目前为止,项目中大家写了不少重复代码,在第一阶段的重构中,我已经尽量消除掉了这些重复代码,接下来不应再出现这些重复代码,除非因为架构需要。

  • 相关阅读:
    Go module学习笔记
    java并发基础及原理
    java并发之内存模型
    https理论及实践
    Mysql查询结果导出Excel表
    mysql清空表数据并重置自增ID
    html a标签链接点击闪动问题解决
    rocketmq-console控制台管理界面配置
    nginx多层反代配置变量proxy_set_header
    nginx 实现浏览器文件下载服务
  • 原文地址:https://www.cnblogs.com/luminji/p/3535742.html
Copyright © 2011-2022 走看看