• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

如何写出“好代码”

其他 .NET西安 1632次浏览 0个评论

一、前言

  项目中使用 Design Pattern 越多越好? 

  哪种 Pattern 比较重要?

  需要学习哪些 Pattern ?

  代码是否可测试?

  对于入门者来说,直接上手学习 Design Pattern 可能会产生很多困惑,认为编程很难。好比修炼神功秘籍,首先得会基本功晓原理;其次才能进阶修炼高阶术法,除非有高人指点,否则轻则自废武功重则走火入魔。

  其实不必, 没有 Design Pattern 也可以写出 “Good Code”。应用程序首先是用来解决问题,不要过分关心 Design Pattern 没有必要为了 Pattern 而 Pattern;但软件开发领域 “Design Pattern” 又很重要,怎么办? 有个建议可以从 “SOLID、DRY” 开始,面向对象编程的基本原则。

  

  面向对象原则 & Design Pattern 两者区别:

  面向对象基本原则:是一种指导规范,应该怎么干,告诉开发者你应该遵循这种规范。 

  Design Pattern :是遵循编程规范解决特定问题的具体实践。

二、面向对象基本原则

  SOLID 由美国软件工程师 Robert C. Martin 总结提出 。维基百科 :https://en.wikipedia.org/wiki/SOLID 。

  SOLID: 

  S – <Single-responsiblity Principle> 单一职责原则 

  O – <Open-closed Principle>开闭原则

  L -<Liskov Substitution Principle>里氏替换原则

  I – <Interface Segregation Principle>接口隔离原则

  D -<Dependency Inversion Principle>依赖倒置原则

  DRY: < Don’t repeat yourself> 不要重复自己原则

 

  1、Single-responsiblity Principle

  单一职责描述:一个类只有一个用途,没有两个用途,没有三个用途。

  好比假设汽车的刹车、油门踏板没有分开设计,被设计成 刹车油门踏板,或者把离合也加进去。想象一下,使用的时候垂直踏下去是刹车,向左偏向下踏是加油,向右向下踏是离合;这样设计的后果 不仅考验驾车者的车技,甚者交通事故率大概率会直线上升。

 

  实践中如果发现类规模越来越大职责越来越多,此时开始着手重构它。

  实践中如果发现一个方法,随着业务变动参数越来越多、方法体越来越臃肿、干的事情越来越多,最显而易见的是 If else 语句变多,此时着手重构它。

 

  题外:分析具体情况,参数多是不是也可以重构为使用一个对象传递,If else  语句多使用 “表驱动法”  、Factory Pattern 解决。

 

  2、Open-closed Principle

  开闭原则描述:软件实体应该对扩展开放,对修改关闭。

  现在各种计步手环特别火,公司安排你做一个集成平台,展示跑步线路。该怎么做?

  假设你是一个软件工程师,加班太多以至于没有时间打扫房间,你雇佣了一个王阿姨打扫房间,一直相安无事,突然有一天王阿姨家有事回家了。刚好这一天心仪的女同事提出去你家做客,而你焦虑房间乱没人打扫。 有了这次经验,你可能会找一个家政公司帮你打扫房间,不用关心王阿姨请假或者有事。 你称之为 “中介者原则”,依赖中介去打扫卫生,而不是依赖某个阿姨,阿姨会有事,中介公司不打样。

  实践中我们依赖抽象不依赖实现,如果发现依赖实现,此时重构它。

  实践中如果写 “Hello World” ,我不会考虑任何原则或者模式。

  现在开始写线路解析程序,遵循 “中介者原则”  定义一个“抽象解析中介” 然后依赖并实现它。 以后不管再来几个手环厂家,我们都可以做扩展,而不用修改已有的解析程序。

 

  3、Liskov Substitution Principle

  里氏替换原则描述:子类或者派生类可以替代其基类或父类,用子类实例替代父类实例不产生负面影响。

  最直观的例子就是,你不能用黄种人作为有色人种或者白色人种的祖先,或者其他人种的祖先作为黄种人的祖先。

  Code Show:

如何写出“好代码”
如何写出“好代码”

        public class YellowRace
        {
            private string _color;

            public YellowRace()
            {
                _color = "Yellow";
            }

            public virtual string GetColor()
            {
                return _color;
            }
        }

        public class WhiteRace : YellowRace
        {
            private string _color;
            public WhiteRace()
            {
                _color = "White";
            }

            public override string GetColor()
            {
                return _color;
            }
        }

        static void Main(string[] args)
        {
            YellowRace yellowRace = new YellowRace();
            WhiteRace whiteRace = new WhiteRace();

            Console.WriteLine($"Yellow Race Skin Color Is: {yellowRace.GetColor()}");
            // 此处使用子类替换父类,会产生负作用 ,
        }

View Code

  上面代码违反 LIP 原则,负面影响:即黄种人,皮肤颜色应是黄色。

  可以重构,创建一个 Mankind 类, 白种人、黄种人都继承它。

如何写出“好代码”
如何写出“好代码”

        public abstract class Mankind
        {
            protected string _color;
            public abstract string GetColor();
        }

        public class YellowRace: Mankind
        {
            public YellowRace()
            {
                _color = "Yellow";
            }

            public override string GetColor()
            {
                return _color;
            }
        }

        public class WhiteRace : Mankind
        {
            public WhiteRace()
            {
                _color = "White";
            }

            public override string GetColor()
            {
                return _color;
            }
        }

View Code

 

  4、Interface Segregation Principle

  接口隔离原则描述:多个客户端特定的接口,好过一个超级通用接口,即客户端不应该实现使用不到的接口,或客户端不应该依赖于不使用的方法。

  实践中曾经阅读过这样的代码违反ISP 。 一个接口中有好多好多行为,其中一个行为在实现类中只有一个类真正用到了,其余的方法体中都是 “throw new NotImplementedException();” ,此时应该着手重构它。

  

  题外,使用抽象类还是接口 ? 接口通常作为行为规范,表示能干什么 Can Do;而抽象类表示是什么 Is A 。例如:打印机能打印,则打印机应该实现一个打印接口,同时打印机是一个电器则可以继承电器基类。

 

  5、Dependency Inversion Principle

  依赖倒置原则描述:应该依赖抽象,而不是具体实现。

  现实中最长用的 ORM 框架,设计的时候遵循此原则,依赖抽象契约而不是某种特定数据库的实现。

  回到雇佣王阿姨打扫房间的例子,依赖中介公司,就是依赖抽象,所有就可以让任何阿姨打扫房间。

 

  6、DRY

  不要重复你自己原则描述:相同的代码不应该存在两份以上。

  实践中相同的代码同时存在多份,此时着手重构它。

 

三、总结

  以上介绍了几种编程原则,遵循这些原则,就可以写出 “Good Code”。

  适用于目前所有的面向对象语言,这些原则指导软件开发,并积累了一些实践。有助于软件代码清晰可读、可扩展、高内聚低耦合,有助于代码重构,清除代码异味。SOLID 被典型应用在,测试驱动开发、敏捷开发、自适应软件开发等领域。

 


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明如何写出“好代码”
喜欢 (0)

您必须 登录 才能发表评论!

加载中……