范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

大龄程序员谈架构经验内行看门道

  前言
  孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说:"对呀,对呀!......回字有四样写法,你知道么?"
  大家好,我是44岁的大龄程序员码农阿峰。阿峰从事编程二十年了,虽然没有成为架构师,却也用过很多种架构。我觉得一招鲜走遍天,架构师常用的那几招我还是会的,听我来说道说道。我以为至少有这几招: 模板方法设计模式 反射 不重复造轮子,集众家所长 架构经验总结
  1).模板方法设计模式的运用
  在一个方法中定义了一个算法的骨架或者步骤,而将一些步骤延迟到子类中去实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某一些步骤。   #父类:     namespace Repository {     ///      /// 数据库存储泛型基类     ///      ///      public class BaseRepository : SimpleClient where T : class, new()     {         public ITenant itenant = null;//多租户事务         public BaseRepository(ISqlSugarClient context = null) : base(context)         {             //通过特性拿到ConfigId             var configId = typeof(T).GetCustomAttribute()?.configId;             if (configId != null)             {                 Context = DbScoped.SugarScope.GetConnectionScope(configId);//根据类传入的ConfigId自动选择             }             else             {                 Context = context ?? DbScoped.SugarScope.GetConnectionScope(0);//没有默认db0             }              itenant = DbScoped.SugarScope;//设置租户接口         }          #region add          ///          /// 插入实体         ///          ///          ///          public int Add(T t)         {             return Context.Insertable(t).IgnoreColumns(true).ExecuteCommand();         }          public int Insert(List t)         {             return Context.Insertable(t).ExecuteCommand();         }         public int Insert(T parm, Expression> iClumns = null, bool ignoreNull = true)         {             return Context.Insertable(parm).InsertColumns(iClumns).IgnoreColumns(ignoreNullColumn: ignoreNull).ExecuteCommand();         }         public IInsertable Insertable(T t)         {             return Context.Insertable(t);         }         #endregion add          #region update         public IUpdateable Updateable(T entity)         {             return Context.Updateable(entity);         }         public int Update(T entity, bool ignoreNullColumns = false)         {             return Context.Updateable(entity).IgnoreColumns(ignoreNullColumns).ExecuteCommand();         }          public int Update(T entity, Expression> expression, bool ignoreAllNull = false)         {             return Context.Updateable(entity).UpdateColumns(expression).IgnoreColumns(ignoreAllNull).ExecuteCommand();         }          ///          /// 根据实体类更新指定列 eg:Update(dept, it => new { it.Status }, f => depts.Contains(f.DeptId));只更新Status列,条件是包含         ///          ///          ///          ///          ///          public int Update(T entity, Expression> expression, Expression> where)         {             return Context.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommand();         }          public int Update(SqlSugarClient client, T entity, Expression> expression, Expression> where)         {             return client.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommand();         }          ///          ///         ///          ///          ///          /// 默认为true         ///          public int Update(T entity, List list = null, bool isNull = true)         {             if (list == null)             {                 list = new List()             {                 "Create_By",                 "Create_time"             };             }             return Context.Updateable(entity).IgnoreColumns(isNull).IgnoreColumns(list.ToArray()).ExecuteCommand();         }                ///          /// 更新指定列 eg:Update(w => w.NoticeId == model.NoticeId, it => new SysNotice(){ Update_time = DateTime.Now, Title = "通知标题" });         ///          ///          ///          ///          public int Update(Expression> where, Expression> columns)         {             return Context.Updateable().SetColumns(columns).Where(where).RemoveDataCache().ExecuteCommand();         }         #endregion update          public DbResult UseTran(Action action)         {             try             {                 var result = Context.Ado.UseTran(() => action());                 return result;             }             catch (Exception ex)             {                 Context.Ado.RollbackTran();                 Console.WriteLine(ex.Message);                 throw;             }         }         public IStorageable Storageable(T t)         {             return Context.Storageable(t);         }         public IStorageable Storageable(List t)         {             return Context.Storageable(t);         }         ///          ///          ///          ///          /// 增删改查方法         ///          public DbResult UseTran(SqlSugarClient client, Action action)         {             try             {                 var result = client.AsTenant().UseTran(() => action());                 return result;             }             catch (Exception ex)             {                 client.AsTenant().RollbackTran();                 Console.WriteLine(ex.Message);                 throw;             }         }          public bool UseTran2(Action action)         {             var result = Context.Ado.UseTran(() => action());             return result.IsSuccess;         }          #region delete         public IDeleteable Deleteable()         {             return Context.Deleteable();         }          ///          /// 批量删除         ///          ///          ///          public int Delete(object[] obj)         {             return Context.Deleteable().In(obj).ExecuteCommand();         }         public int Delete(object id)         {             return Context.Deleteable(id).ExecuteCommand();         }         public int DeleteTable()         {             return Context.Deleteable().ExecuteCommand();         }         public bool Truncate()         {             return Context.DbMaintenance.TruncateTable();         }         #endregion delete          #region query          public bool Any(Expression> expression)         {             return Context.Queryable().Where(expression).Any();         }          public ISugarQueryable Queryable()         {             return Context.Queryable();         }          public (List, int) QueryableToPage(Expression> expression, int pageIndex = 0, int pageSize = 10)         {             int totalNumber = 0;             var list = Context.Queryable().Where(expression).ToPageList(pageIndex, pageSize, ref totalNumber);             return (list, totalNumber);         }          public (List, int) QueryableToPage(Expression> expression, string order, int pageIndex = 0, int pageSize = 10)         {             int totalNumber = 0;             var list = Context.Queryable().Where(expression).OrderBy(order).ToPageList(pageIndex, pageSize, ref totalNumber);             return (list, totalNumber);         }          public (List, int) QueryableToPage(Expression> expression, Expression> orderFiled, string orderBy, int pageIndex = 0, int pageSize = 10)         {             int totalNumber = 0;              if (orderBy.Equals("DESC", StringComparison.OrdinalIgnoreCase))             {                 var list = Context.Queryable().Where(expression).OrderBy(orderFiled, OrderByType.Desc).ToPageList(pageIndex, pageSize, ref totalNumber);                 return (list, totalNumber);             }             else             {                 var list = Context.Queryable().Where(expression).OrderBy(orderFiled, OrderByType.Asc).ToPageList(pageIndex, pageSize, ref totalNumber);                 return (list, totalNumber);             }         }          public List SqlQueryToList(string sql, object obj = null)         {             return Context.Ado.SqlQuery(sql, obj);         }          ///          /// 根据主值查询单条数据         ///          /// 主键值         /// 泛型实体         public T GetId(object pkValue)         {             return Context.Queryable().InSingle(pkValue);         }         ///          /// 根据条件查询分页数据         ///          ///          ///          ///          public PagedInfo GetPages(Expression> where, PagerInfo parm)         {             var source = Context.Queryable().Where(where);              return source.ToPage(parm);         }          public PagedInfo GetPages(Expression> where, PagerInfo parm, Expression> order, OrderByType orderEnum = OrderByType.Asc)         {             var source = Context.Queryable().Where(where).OrderByIF(orderEnum == OrderByType.Asc, order, OrderByType.Asc).OrderByIF(orderEnum == OrderByType.Desc, order, OrderByType.Desc);              return source.ToPage(parm);         }          public PagedInfo GetPages(Expression> where, PagerInfo parm, Expression> order, string orderByType)         {             return GetPages(where, parm, order, orderByType == "desc" ? OrderByType.Desc : OrderByType.Asc);         }          ///          /// 查询所有数据(无分页,请慎用)         ///          ///          public List GetAll(bool useCache = false, int cacheSecond = 3600)         {             return Context.Queryable().WithCacheIF(useCache, cacheSecond).ToList();         }          #endregion query          ///          /// 此方法不带output返回值         /// var list = new List();         /// list.Add(new SugarParameter(ParaName, ParaValue)); input         ///          ///          ///          ///          public DataTable UseStoredProcedureToDataTable(string procedureName, List parameters)         {             return Context.Ado.UseStoredProcedure().GetDataTable(procedureName, parameters);         }          ///          /// 带output返回值         /// var list = new List();         /// list.Add(new SugarParameter(ParaName, ParaValue, true));  output         /// list.Add(new SugarParameter(ParaName, ParaValue)); input         ///          ///          ///          ///          public (DataTable, List) UseStoredProcedureToTuple(string procedureName, List parameters)         {             var result = (Context.Ado.UseStoredProcedure().GetDataTable(procedureName, parameters), parameters);             return result;         }     }      ///      /// 分页查询扩展     ///      public static class QueryableExtension     {         ///          /// 读取列表         ///          ///          /// 查询表单式         /// 分页参数         ///          public static PagedInfo ToPage(this ISugarQueryable source, PagerInfo parm)         {             var page = new PagedInfo();             var total = 0;             page.PageSize = parm.PageSize;             page.PageIndex = parm.PageNum;             page.Result = source.OrderByIF(!string.IsNullOrEmpty(parm.Sort), #34;{parm.Sort} {(parm.SortType.Contains("desc") ? "desc" : "asc")}")                 .ToPageList(parm.PageNum, parm.PageSize, ref total);             page.TotalNum = total;             return page;         }     } }     #子类:         [AppService(ServiceLifetime = LifeTime.Transient)]     public class GenDemoRepository : BaseRepository     {         #region 业务逻辑代码         #endregion     }
  现在大家都学精了,都使用泛型基类来简化重复的代码,标准的架构还是按经典的三层架构标准来搭建。这个是基本功,不用说太细。
  2).反射
  反射:是.Net Framework和.Net Core提供的一个帮助类库,可以访问dll的metadata,并且使用它。
  反射反射,程序员的快乐  ///          /// 注册引用程序域中所有有AppService标记的类的服务         ///          ///          public static void AddAppService(this IServiceCollection services)         {             //var assemblies = AppDomain.CurrentDomain.GetAssemblies();              string []cls = new string[] { "Topaut.Repository", "Topaut.Service", "Topaut.Tasks" };             foreach (var item in cls)             {                 Assembly assembly = Assembly.Load(item);                 Register(services, assembly);             }         }          private static void Register(IServiceCollection services, Assembly assembly)         {             foreach (var type in assembly.GetTypes())             {                 var serviceAttribute = type.GetCustomAttribute();                  if (serviceAttribute != null)                 {                     var serviceType = serviceAttribute.ServiceType;                     //情况1 适用于依赖抽象编程,注意这里只获取第一个                     if (serviceType == null && serviceAttribute.InterfaceServiceType)                     {                         serviceType = type.GetInterfaces().FirstOrDefault();                     }                     //情况2 不常见特殊情况下才会指定ServiceType,写起来麻烦                     if (serviceType == null)                     {                         serviceType = type;                     }                      switch (serviceAttribute.ServiceLifetime)                     {                         case LifeTime.Singleton:                             services.AddSingleton(serviceType, type);                             break;                         case LifeTime.Scoped:                             services.AddScoped(serviceType, type);                             break;                         case LifeTime.Transient:                             services.AddTransient(serviceType, type);                             break;                         default:                             services.AddTransient(serviceType, type);                             break;                     }                     //Console.WriteLine(#34;注册:{serviceType}");                 }                 else                 {                     //Console.WriteLine(#34;注册:{serviceType}");                 }             }         }     }
  官方各种Service注入IOC容器都是手写,框架作者利用反射实现了减少大量繁琐的固定写法,对于普通项目而言,反射的性能损耗微不足道的。
  3).不重复造轮子集众家所长
  有时程序员喜欢浪费生命去重复造轮子,如果是为了学习一次怎么造轮子是值得肯定的。否则就是吃饱了没事干闲的。现在是最好的时代(好多开源组件可用),也是最坏的时代(行业太卷)。框架作者使用了糖果大数据的开源组件SqlSugar来实现多数据库类型的支持,还有多租户,读写分离,分表分库这些数据库层面的数据存储方案。实现前后端分离参考了一些其他的优秀Vue实现的Admin框架。
  在线体验官方文档:http://www.izhaorui.cn/doc vue3.x版本体验:http://www.izhaorui.cn/vue3 vue2.x版本体验:http://www.izhaorui.cn/admin 账号密码:admin/123456
  https://gitee.com/izory/ZrAdminNetCore/

勿忘九一八丨从中日女性服饰对比,看清日本冰箱论的荒谬前不久,上海佘山国家森林公园月湖旁草地上的雕塑群在网上引起了广泛争议。其中部分雕塑人物形似身穿和服。有网友质疑为何要在公园树立这些粗制滥造?既不美观也不符合情感。服装是一种重要的文全球排第一的洗衣机继冰箱空调之后,中国品牌再一次登顶国内洗衣机产业经过三十多年的摸爬滚打,有着较成熟的产业链和市场。从全国范围来看,我国洗衣机市场普及程度已经超过了七成,其中城镇市场普及程度九成以上,就连农村市场也超过了五成。中国品换个口味吃主食糙米所含的B族维生素,比白米多四五倍,白米中的维生素B1煮熟后全部消失,糙米则能保留80,且脂肪也是白米的四倍(不用担心,这是有益的脂肪)。维生素B1参与糖代谢,帮助人体对碳水化合这个主食厉害了,好吃又顶饱,宝宝也爱不释手咱们平时吃饭最不可缺少的就是主食了,花卷算是家喻户晓的一种,好吃顶饱,成本也便宜,今天要分享的便是香煎花卷的做法,相较于白面馒头的寡淡,花卷花样更多,口感更鲜香,口味也可以自己搭配香菜保存不要直接放冰箱,教你2个好方法,放一年照样翠绿新鲜导语香菜保存不要直接放冰箱,教你2个好方法,放一年叶子照样翠绿新鲜!大家好,我是傻姐美食,大家对于香菜并不陌生,它是我们生活中不可缺少的调味品,它既可以当作调味品也可以当作蔬菜。不长期吃久冻的肉会致癌?冰箱里的肉冻多久就不能吃了?今天讲清楚自改革开放以来国民经济迅速发展,现代人再也不用过吃不饱穿不暖的生活,想吃什么基本都能得到满足,伴随经济水平的不断提高,人们开始追求高品质的生活,也让越来越多的国民爱上了吃肉。有一些躲懒不做3件事,冰箱至少增加4种致病菌!华西医生来看正确做法低温又密封的冰箱是大多数人心目中储存食物的最佳位置。尤其是在这个特殊时期,哪家的冰箱要是能够被各种蔬菜水果肉塞得满满当当,那真是恨不得在朋友圈这样走路图片来源发表情但你知道吗?冰箱浏览故宫你必须知道的十件事故宫那么大,如何不踩雷!接下来给大家讲清楚,故宫到底应该怎么玩NO1故宫唯一的入口是午门,但是强烈建议你去故宫的话,千万别从天安门方向走,一定要从东华门那个方向走过去,为什么呢?首尊崇科学,反对科学霸权主义(7)波普尔证伪检验科学标准?卡尔波普尔是英国科学哲学家,主要著作有科学发现的逻辑历史决定论的贫困等。卡尔波普尔波普尔在科学发现的逻辑中断定可以作为经验的或科学的,还是非科学甚至伪科学,划界的标准不是可证实性而曝吉林锁定山东旧将!2米08便宜实用曾狂砍4214联手琼斯再冲8强吉林队今年夏天在阵容方面没有特别大的调整力度,只通过选秀大会签下了2米10的张斌,并且和深圳队达成协议,租借到了2米14的19岁小将彭森傲,虽然内线终于迎来了两名两米以上的新人,但高原已经不是荒原了,鲜花一直在这里绽放高原浪漫李江我至今还记得班长退伍前曾说的话,高原的风很粗狂,玫瑰也从未在这片土地上生长,但如果你喜欢浪漫,这里并非寸草不生。那时的我虽然听不懂这句话的含义,却默默记在了心里,并一直
走路快和走路慢,谁更容易长寿?研究得出两者衰老或相差16岁如何能够长寿,自古以来都是大家比较关心的一个话题,因为只有长寿,才能够享受更多的天伦之乐。除了老年人应该注重这个问题以外,在年轻的时候就应该了解一些关于长寿的秘诀,掌握养生的方法。俄军用燃烧弹打空地,没几天亚速营却投降,这才是真正的战争艺术5月中旬,俄军罕见动用大量燃烧弹火烧亚速钢厂,整个厂区都被密集的铝热燃烧弹覆盖。但是我们要看到,主要由混凝土和钢铁设施组成的厂区,因为平常主要是冶铁,大部分材料都是耐高温的,几乎没出生14天被扔垃圾桶,养父扛煤气罐供成博士后,父母砸50万要认女2001年冬天,湖北孝感正读初三的肖晶晶,被一个突如其来的噩耗迎面痛击她亲爱的妈妈祁春兰,被查出到了癌症晚期。之前妈妈身体一直不好,她知道,所以每天回家做完作业后,她会主动帮着做些男女因28万彩礼被迫分手,6个月后,女孩想挽回遭拒我有老婆了自古以来,两个人从相爱到组成一个家庭总是要经历各种各样的事,有来自于爸妈以及亲戚朋友的各种建议与认可,也有正式结婚之前的房车礼金陪嫁等一系列的问题。如若有一项谈不妥,那么这个婚姻就从小学就开始看的秦时明月要2046年完结?还真是有生之年呀海贼不识王路飞,便称英雄也枉然!大家好,我乌龙君又双叒叕来了5月10号某瓣公布的一则消息可以说是震惊四座,消息的来源是一张海报,而上面则是明晃晃地写着,秦时明月之亡秦必楚这部作品将香港大佬向华强儿媳妇郭碧婷官宣怀二胎消息!三年两娃这速度绝了520是个美好又甜蜜的日子!今天要吃的狗粮可不仅仅是自己身边的人的呦!娱乐圈的好消息也是一件接一件!时隔两年郭碧婷又官宣了怀二胎消息!网友三年两胎,身体恢复的过来吗?今天(520)12种懒人花,一年四季都能开,阳台养花必备养花是点缀生活,让人能在花草间寻得一点平静自然,所以咱们还是养些懒人花吧,适合室内盆栽,生长有规律,爱开花的植物,无论你是新手还是杀手,都可以养好!长寿花长寿花现在越来越普及了,就两岸探探探台湾人均GDP飚高,为什么台湾民众普遍无感?这个两岸真相不得不知台湾地区领导人蔡英文日前宣称,2022年台湾人均GDP或达到3。6万美元,有望时隔20年,再度超过韩国,又因为日元贬值,岛内部分网民喊出赶超日本的口号。可是从台湾有关电视节目可以看北京市继续暂停堂食暂不返校,丰台区全域提级管控科技日报记者华凌5月19日,本市开展的区域核酸筛查,共采样检测1500万人,检出5管混采阳性,其中海淀区3管,东城区怀柔区各1管。落位管控复核转运流调溯源等工作已同步进行中。5月2德国比利时发现猴痘确诊病例综合外电消息,比利时当地时间19日发现头两例猴痘确诊病例,德国也于19日发现了首例猴痘病例。此外,西班牙当地时间20日新增14例猴痘确诊病例。据路透社布鲁塞尔报道,比利时的两例病例如此寂寞难耐?男子会小三,影响一座城校花约男友,隔离五千人520已到,按说爱情是个甜蜜的东西。问世间情为何物,直教人生死相许。但是,有些时候是问世间情为何物,一时间妖魔乱舞。爱情不该是只为自己愉悦,而去影响别人吧?故事一,私会情人。淄博男