Foxlair

笔记 - Unix编程艺术

· q8f13

笃信模块化,注重正交性和紧凑性

用API作为串接的线索,来组织模块

软件开发的良好习惯:先定义接口,编写简要注释,对其进行描述,最后再编写代码

模块粒度过小或过大都会导致缺陷密度上升

SPOT原则

提高紧凑型的一种方法 围绕“解决一个定义明确的问题”的强核心算法组织设计

分离的价值:崇尚简洁 尽量思考最少能做的事情,不要带着假想行动,而是从零开始

软件是多层的,设计思路: 自顶向下(从抽象到具体)和自底向上(从具体到抽象) 自顶向下适用于以下三个条件都成立:

一般多见于应用软件编程 自底向上的设计更灵活,在高层设计变化后,仍然可以重用

胶合层

Unix编程风格——强调模块化和定义良好的API——其影响之一: 倾向于把程序分解为由胶合层连接的库的集合,特别是共享库

程序分层 GUI/高层逻辑;库程序;胶合层程序。下图以GIMP为例 Unnamed QQ Screenshot20170726142129.png

OO有其局限性,设计理念价值在图形系统,UI和某些仿真程序之外的领域内认可程度待考

模块式编码

管道通信文本化

数据文件的元格式

代码的可显性

推动逻辑的程序应该具备监控开关,这些监控也仅仅是针对组件之间的文本流(表达了执行过程和可能出问题的环节,提高可显性)

在GUI的设计中,让可显性的特质有所体现,但不要妨碍最终用户的使用习惯 聪明的UI设计:找到方法可以访问具体细节,又不让它们太显眼

FreeCiv的案例

追求代码的透明,不要在具体操作的代码上叠放太多的抽象层

追求透明和可显的编码习惯:      - 程序调用层次的最大静态深度(不考虑递归)如果大于4则需要考虑      - 追求代码的不变性质。利于推演代码发现有问题的部分      - API的各个函数调用是否正交。或是否存在太多的标记位,使一个调用要完成多个任务?      - 顺手可用的关键数据结构,或全局唯一的记录器用来捕获高层次状态。让这个状态易于形象化或检验      - 数据结构与其代表的外部实体之间,是否是清晰的一对一映射      - 尽量避免函数的hack性质      - no magic number

避免过度保护底层细节,为故障检测带来困难

如果有难以文本化的处理对象需要提升可见性和透明度,编写数据文件文本化的工具。让复杂的二进制对象在调试过程中能和文本格式进行无损转换 如果二进制对象是动态或非常大的,那么可以考虑编写对象专用的浏览器

通过编写开发者手册来增加代码的可维护性

微语言:更具表达力的语言意味着程序更短,bug更少 复杂度上升到一定程度之后,考虑将语言中的控制流从隐式提升到显式

数据驱动       关于配置文件      - 哪些配置不应该暴露给最终用户           - 能用脚本包装或管道实现的任务,就不要用配置开关      - 在增加配置选项之前,先考虑:           - 功能是否一定要存在?           - 能不能用某种无伤大雅的方式改变常规行为而无需这个配置           - 少考虑GUI的配置性,而多考虑实用性           - 这个配置所附加的行为是否应该抛给单独的独立程序

最小立异原则      - 避免设计违反通用概念的全新接口模型      - 如有可能,尽量允许用户将接口功能委派给熟悉的程序来完成

接口设计评估      - 简洁           - 以较少的动作/状态变化来保证较多的作用效果      - 表现力           - 触发广泛的行为           - 最具表现力的接口可以启动设计者没有预见的行为组合,但仍然对最终用户有效并保持一致性      - 易用           - 为了让用接口用户需要记忆尽量少的内容      - 透明           - 不用记忆多少数据或程序的相关状态           - 自然地给出中间过程的反馈。所见即所得      - 脚本化能力           - 接口能被其他程序共用的能力。提升泛用程度

过滤器设计模式      - 宽进严出(postel原则)      - 不丢弃不需要的信息,单独滤出来并保留      - 过滤时不增加无用数据

cantrip模式      - 无输入无输出,只调用一次,产生退出状态数值

源模式      - 无输入,启动条件控制输出内容(如ls)

接收器模式      - 只接纳标准输入,无输出。启动条件控制对输入数据的行为

编译器模式      - 从命令行接受文件或资源,转换之,再用改变后的名字输出。不需要用户交互      - 常见于格式转换命令

ed模式      - 文本编辑器。接受文件并进行所见即所得的编辑

Roguelike模式      - 用ascii字符形成的GUI交互

“引擎和接口分离”模式      - 程序的核心算法和逻辑规格等(引擎)与“接口“(用户命令、显示结果、交互和额外信息等)部分分离      - 引申出MVC设计模式      - 实践中,VC部分通常结合更紧密,往往只在需要多重视图的情况下才分开

MVC衍生      - 配置者/执行者组合           - 逻辑部分专精逻辑,不考虑GUI或表现等对用户更友好的设计           - 配置部分专精打磨GUI和UX,方便用户配置等功能           - 两者通信通道中实现互相配合            - 假脱机/守护进程           - 前端的作用就是把请求或数据扔进池           - 守护进程就是负责轮询看池里面是否有需要处理的内容。成功后从池里面删掉

     - 驱动/引擎组合(???)      - C/S组合

基于语言的接口模式      - 内嵌脚本语言      - 如emacs,GIMP

长时间的操作要提供进度条——帮助用户有效地分时利用大脑,暗示等待完成的过程中可以去干点别的 GUI不要乱出警告和确认,焦点不在父窗口的时候应该避免这些信息 界面设计师的工作是方便用户,而不是在用户面前碍眼

接口整体应遵从最小立异原则,但信息内容应该符合最大惊奇原则——仅对偏离期望的看情况详细说明

过早优化乃万恶之源

永远不要将核心数据结构和时间关键循环抛出缓存

选择合适的时机刷新GUI,而不是每条都刷,适当攒一波

微信截图_20170726182152.png

控制复杂度的困难在于:如何在代码量,接口复杂度和实现复杂度三者之间进行权衡

最简原则暗示:选择需要管理的上下文环境,并且按照边界所允许的最小化方式构建程序

Unix吝啬原则:首先寻找小巧程序的解决方案。如果单个小程序无法完成这项工作,尝试在现有框架结构内构造一个协作小程序工具包来解决问题。如果两者都失败,才自由地构建一个巨型程序(或一个新框架)

创建框架时,牢记分离原则:框架是一种机制,应该尽可能少地包含策略。尽可能多地将需求和行为分解到使用框架的模块中去

#note   #programming   #code   #unix