《写给大家看的设计书》是一本讲述设计原理的书。作者将其丰富的设计经验用简洁凝练的笔调总结出四个设计原则:亲密性、对齐、重复、对比。
当然写本文的目的不是为了介绍这本书,主要为了探讨与亲密性、对齐原则相关的一些最佳编程实践。
一:亲密性
亲密性原则是指:将相关的项组织在一起,移动这些项, 使它们的物理位置相互靠近,这样一来,相关的项将被看作凝聚为一体的一组,而不是一堆彼此无关的片段。这有助于组织信息,减少混乱,为读者提供清晰的结构。
说了那么多,那亲密性原则和软件设计有没有一毛钱关系呢?好好想想,没错就是高内聚、低耦合原则,这个原则是不是和亲密性原则有异曲同工之妙?
高内聚、低耦合是软件设计的一个基本的原则,是衡量软件质量的标准之一。
耦合是指元素之间的依赖的度量。这里的元素可以指函数、类、对象、模块、库、组件、服务以及系统等等。低耦合是指元素之间不要过度依赖。
内聚是指软件元素相关性的度量。高内聚是指某个元素具有相关性很高的职责,不做多余的事,反之则是低内聚。
高内聚、低耦合归根到底是为了使代码具有可读性、复用性、易于维护、易于扩展,这样加班的程序猿就大大减少了。
除了高内聚、低耦合原则还有没有什么原则和亲密性原则类似呢?有,那就是面向对象五大原则中的单一职责原则。单一职责原则是指一个类有且仅有一个职责,不要把不同的职责放到一个类中。简单来说就是该干嘛干嘛去,不要牝鸡司晨,不要狗拿耗子多管闲事,不要写出意大利面条一样的代码,牵一发而动全身,加大了阅读者的思维负担,不易于扩展,不易于维护。
二:对齐
对齐原则是指:任何元素都不能在页面上随意安放。每一项都应该与页面上的某个内容存在某种视觉联系。如果页面上的一些项使对齐的,这会得到一个更内聚的单元。即使对齐的元素物理位置是彼此分离的,但在你眼里,它们之间也会有一条看不见的线把它们连在一起。尽管你可能通过分开放置某些元素来指示它们的关系,单对齐原则很“神奇”,它会告诉读者,即使这些项并不靠近,单它们属于同一组。
对齐原则也可以适用于代码中,代码适当缩进对齐可以增加可阅读性,减轻阅读者的思维负担。
我们在写代码的时候,类、类的方法、方法中的代码块已经代码中的代码块一般都要适当地缩进对齐。在文件顶层的语句,例如大多数类声明,根本不缩进。类中的方法相对该类缩进一个层级。方法的实现相对声明缩进一个层级。代码块的实现相对于其容器代码块缩进一个层级,以此类推。
程序非常依赖这种缩进对齐模式。他们从代码行左边查看自己在什么范围中工作。这让他们可以快速跳过与当前关注的代码无关的范围,例如if或者while之类的语句。眼光扫过左边,查找新的方法声明、新的变量、新的代码块或者新的类。如果没有缩进的话,代码会变的一团糟,无法轻松阅读。
试看代码清单1和代码清单2,你可以快速看出代码清单2表示的含义,而代码清单1则需要思考停顿一下才能理解清楚。
代码清单1:
<!DOCTYPE html> <html> <body> <h4>Fruit: </h4> <ol> <li>Apples</li><li>Bananas</li> <li>Lemons</li> <li>Oranges</li> </ol> </body> </html>
代码清单2:
<!DOCTYPE html> <html> <body> <h4>Fruit: </h4> <ol> <li>Apples</li> <li>Bananas</li> <li>Lemons</li> <li>Oranges</li> </ol> </body> </html>
缩进对齐如此重要,所以Python把缩进标明代码块作为了语法的一部分。
见下面的Python代码清单3和代码清单4,代码清单4中while语句下面的代码块没有适当缩进了是不符合语法规范的,会报错。而代码清单3的设当缩进符合语法规范,。
代码清单3:
# -*- coding: UTF-8 -*- import socket HOST = '192.168.0.124' PORT = 8000 def send_and_recv(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) while True: cmd = input("Please input cmd:") s.sendall(cmd) data = s.recv(1024) print(data) s.close() if __name__ == '__main__': send_and_recv()
代码清单4:
# -*- coding: UTF-8 -*- import socket HOST = '192.168.0.124' PORT = 8000 def send_and_recv(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) while True: cmd = input("Please input cmd:") s.sendall(cmd) data = s.recv(1024) print(data) s.close() if __name__ == '__main__': send_and_recv()
至于重复和对比原则就和编程相关实践没什么关系了。