都是一样的

简介:

我家小孩最喜欢的一句口头禅就是“都是一样的”。每当他看到两件相似的东西时,就会说“都是一样的”。其实,程序设计也是如此,不管语言的变化有多大,其基本的编程思想和设计本质,都是殊途同归。

最近看了Jonathan Snook的作品《Javascript捷径教程》(英文书名:Accelerated DOM Scripting with Ajax, APIs, and Libraries),他带领读者构建了一个简单的动画对象。简单的例子,轻描淡写的描述,我却觉得颇有感悟,似乎展现了朴素的基本设计思想。书中这样写道:

页面里要用到的动画对象一般都不止一个,所以应该把它定义成一个类。定义一个有5个参数的函数:要加上动画的元素、要改变的属性、属性的起始值、属性的结束值、动画的持续时间。

function Animation(element, property, from, to, duration){}

不管编写什么代码,都应该先把实现想透彻。每个决定都有正反两方面的后果,你应该想清楚每个决定的原因。

这代表一个朴素的思想,那就是从实现原理来进行设计决定。注意这里的实现原理,并不是要关注实现的细节,而是要考虑影响实现的因素,并从调用者的角度思考接口或函数的输入与输出值。以本例而言,如果事先不明确动画效果的营造方式,是根据时间的变化动态变更element属性的方式来完成,就无法确定Animation函数。设计不是空中楼阁,抽象固然是重要的,但功能实现的基本原理仍然需要事先思考通透,否则,设计就可能走弯路。拿到一个功能,先要弄清楚它的目标是什么,有没有质量属性的要求,未来的变化如何,还有这一功能的实现原理。例如,我们要提供服务定制的功能,就需要实现明确“服务”的定义,如何完成服务的注册,服务的发布,服务的订阅,谁会订阅这些服务,服务的安全如何保障,如何解决服务与实现的脱耦。只有把这些问题想清楚了,设计才会靠谱。

看看前面的代码,元素ID是作为一个字符串传递进来的,那么在动画对象中获取该元素就有两种方法:一是通过DOM方法document.getElementById();二是采用Javascript库的调用,如${}。……既然我们想让这个动画对象能适合各种情况,那还是用DOM方法比较好,保证它不依赖于任何库。

function Animation(element, property, from, to, duration) {  var el = ducument.getElementById(element);  if (!el)  return  false; }

这段话仍然体现了一种设计决策。它的实现目标是不与任何JS库耦合。这就需要保证实现的通用性。

要是你打算执行动画的元素没有ID怎么办呢?为了让这个类更灵活,让我们把它改成既可以传入元素引用,又可以传入ID字符串。如果传入的是ID字符串而不是对象引用,程序就会通过DOM方法去获取元素。两全其美!

function Animation(element, property, from, to, duration) {  var el = element;  if ( typeof el ==  'string') el = document.getElementById(element);  if (!el)  return  false; }

这又是一种编码修炼了。除了要在设计上保证灵活性之外,我们在编码时也需养成保证代码完整性与健壮性的习惯,并体贴地为调用者着想。有这么一条设计原理,就是伯斯塔尔法则(Postel's Law):“发送时要保守;接收时要开放。”这里的实现无疑遵循了这样一个法则。我们在编码时,考虑到这些因素了吗?

Ok,继续我们的阅读。

实例化一个对象要用到5个参数,但一眼看上去很难看出参数里的那些数字都代表什么含义。……为此你可以把参数改成字面量对象,键的名称看起来更直观一些。而且如此改动能使API更加灵活,因为即使今后增加了更多的参数,实例化对象的代码也不会变得更复杂。

function Animation(options) {  var el = options.element; }  var options = { element:document.getElementById( 'elementId'), property:  'left', from:0, to:200, duration:1000 };

无疑,这体现了面向对象的“封装”思想。通过封装既保证了代码的清洁与可读性,同时还有利于未来的扩展。这与OCP(开放-封闭原则)是一脉相承的。代码是有结构的,或者体现为函数,或者体现为对象,事实上都是一种按照属性与职责进行的分类。分类是保持清洁、避免重复的唯一法门。从简朴的角度来说,所有的设计其实都是在做着分类的游戏。分类体现了定义的抽象,职责的分配,结构的划分;如果再加上类别之间的协作,就是设计的全部了。







本文转自wayfarer51CTO博客,原文链接:http://blog.51cto.com/wayfarer/558510,如需转载请自行联系原作者

相关文章
|
8天前
|
人工智能 自然语言处理 API
深入浅出LangChain与智能Agent:构建下一代AI助手
LangChain为大型语言模型提供了一种全新的搭建和集成方式,通过这个强大的框架,我们可以将复杂的技术任务简化,让创意和创新更加易于实现。本文从LangChain是什么到LangChain的实际案例到智能体的快速发展做了全面的讲解。
279541 52
深入浅出LangChain与智能Agent:构建下一代AI助手
|
9天前
|
设计模式 人工智能 JSON
一文掌握大模型提示词技巧:从战略到战术
本文将用通俗易懂的语言,带你从战略(宏观)和战术(微观)两个层次掌握大模型提示词的常见技巧,真正做到理论和实践相结合,占领 AI 运用的先机。
237784 4
|
9天前
|
NoSQL Cloud Native Redis
Redis核心开发者的新征程:阿里云与Valkey社区的技术融合与创新
阿里云瑶池数据库团队后续将持续参与Valkey社区,如过往在Redis社区一样耕耘,为开源社区作出持续贡献。
Redis核心开发者的新征程:阿里云与Valkey社区的技术融合与创新
|
9天前
|
关系型数据库 分布式数据库 数据库
PolarDB闪电助攻,《香肠派对》百亿好友关系实现毫秒级查询
PolarDB分布式版助力《香肠派对》实现百亿好友关系20万QPS的毫秒级查询。
PolarDB闪电助攻,《香肠派对》百亿好友关系实现毫秒级查询
|
3天前
|
机器人 Linux API
基于Ollama+AnythingLLM轻松打造本地大模型知识库
Ollama是开源工具,简化了在本地运行大型语言模型(ile优化模型运行,支持GPU使用和热加载。它轻量、易用,可在Mac和Linux上通过Docker快速部署。AnythingLLM是Mintplex Labs的文档聊天机器人,支持多用户、多种文档格式,提供对话和查询模式,内置向量数据库,可高效管理大模型和文档。它也是开源的,能与Ollama结合使用,提供安全、低成本的LLM体验。这两款工具旨在促进本地高效利用和管理LLMs。
77967 19
|
10天前
|
消息中间件 Cloud Native Serverless
RocketMQ 事件驱动:云时代的事件驱动有啥不同?
本文深入探讨了云时代 EDA 的新内涵及它在云时代再次流行的主要驱动力,包括技术驱动力和商业驱动力,随后重点介绍了 RocketMQ 5.0 推出的子产品 EventBridge,并通过几个云时代事件驱动的典型案例,进一步叙述了云时代事件驱动的常见场景和最佳实践。
246779 2
|
7天前
|
物联网 PyTorch 测试技术
手把手教你捏一个自己的Agent
Modelscope AgentFabric是一个基于ModelScope-Agent的交互式智能体应用,用于方便地创建针对各种现实应用量身定制智能体,目前已经在生产级别落地。
|
11天前
|
弹性计算 安全 API
访问控制(RAM)|云上安全使用AccessKey的最佳实践
集中管控AK/SK的生命周期,可以极大降低AK/SK管理和使用成本,同时通过加密和轮转的方式,保证AK/SK的安全使用,本次分享为您介绍产品原理,以及具体的使用步骤。
101885 3
|
10天前
|
自然语言处理 Cloud Native Serverless
通义灵码牵手阿里云函数计算 FC ,打造智能编码新体验
近日,通义灵码正式进驻函数计算 FC WebIDE,让使用函数计算产品的开发者在其熟悉的云端集成开发环境中,无需再次登录即可使用通义灵码的智能编程能力,实现开发效率与代码质量的双重提升。
95465 4
|
2天前
|
人工智能 自然语言处理 API
Claude3是什么?
Claude 3最近备受各大媒体瞩目,成为了AI领域备受关注的新宠。在ChatGPT推出更高版本之前,Claude 3已经被公认为是语言类AI工具中的佼佼者,特别在处理逻辑性和长篇上下文方面表现突出。然而,与此同时,Claude 3的注册流程也备受诟病,被认为是所有AI工具中最为复杂的之一。 这篇内容教大家 注册Claude 3 以及升级 教程。
13684 1
Claude3是什么?