架构师修练 I - 超级代码控
可实现的是架构,空谈是概念 So don't tell me the concepts show me the code! “不懂编码的架构师不是好架构师” 好架构师都是超级代码控。
代码是最好的老师
从代码中学习设计的思想、方法是提升类库设计能力、印证你所了解的概念与理论这就是架构师看代码的观点。
基本准备
一个类库可能有数千个类上万个方法,应该如何去看呢? 在看代码前我们需要进行一些什么样的准备呢 ?
- 设计模式 - 最标准的23种设计模式基本上要有一个了解,可能一下子不能理解他们的用法,但一定要记下他们的英文名字和基本的用途,如:Factory, Wrapper (Decorator), Command, Builder等 。
- 语言规范 - 熟读语言本身的官方编码规范与命名规则,这是共同的标准,也是从官方得到写代码的第一指导。
- 要看懂UML中对类的图形表示方法(类、接口、抽象类、继承关系、使用关系)
看代码的方法
这里所提供的方法就先以C#作为语言基础,因为C#有极为规范的的语法规则。.net 的文档在类库方面的文档是最完整也是最易读的。以.net framework作为起点会是一个很好的练习入口。在开始前我还推荐一下大家需要有一个反编译工具我用的是.NET Reflector, 用反编译工具不是让你去抄代码(代码本身是没有多大价值的,价值的核心在于设计)而是可以更深入地了解到代码是怎样实现的。用反编译工具看微软的代码会看到很多的不同的,你会发现大最设计得非常有意思的内部类 (Internal) 。从中大至可以推断出微软的开发方法,“在外部接口完全一至的情况下,让程序员编写的自由度最大边界就是内部类与内部方法” 你可以马上动手先看看 System.Web.Mvc.dll 的实现
要点:多问为什么,带着问题看代码——为什么这样写(存在理由)?为什么这样设计(出发点)? 由你来写又将如何实现?
看命名
以面向对象的语言为例,大多会在名字内带有具体的用法信息,从名称推算可能使用的模式及实现
带有模式印记的类:
- TagBuilder - 以Builder模式实现的Html标记的构建器
- StringBuilder - 以Builder模式实现的字符串构造建器
- XXXXWriter - 以构建器模式实现的各种写入器
- ConnectionFactory - 数据库连接对象构造工厂
XXX+模式名 是惯用的对模式类的一种命名规则
找到了模式实现如果你看不懂,那恭喜你这就是学习的机会到了,马上翻开设计模式与实现类进行对照印证,这个过程可以加速模式在你大脑中的印象与加深理解。(模式是架构师的大杀招,能不能上档次就看对模式的理解与认识了,一有机会就应该学)
带有家族印记的类:
XXX+Base - 抽象类
基类名+XXX - 某抽象类的子类
是继承关系一种常见的命名规则。
注:每一种基础语言会有自身的命名规则,所以必须对官方提供的命名规则烂熟于胸,既可以学习别人怎么写代码也可以规范自己的代码写法。
做完这两个练习基本上你可以在不看 Classes References(类手册)的情况下一下子了解一大堆类的存在与用法。
看接口
接口在设计中有着极为重要的地位,结构再复杂的系统到了接口级别基本上都会很简单。而且也是判定这个类库设计是否成熟的一种标准。接口与接口间的定义就定义整个系统的基本框架。看接口的最基本意义就是深入理解类库设计者的设计思路与了解类库最核心的能力。
这里我们以 IRepository 为例来讲讲怎么去看接口 (如果想深入了解IRepostiory的朋友可以阅读我之前的文章:“Repository模式与UnitOfWorks模式的运用” )
我以 IRepository 为例是因为它的共识度很大,而实现起来可以很庞大也可以很小,众所周知IRepository提供的就是对某个实体的CURD(增加、更新、读取、删除)的一个接口。那么当我们看到它的存在时,应该可以推断出另一个接口:IUnitOfWork 因为它们往往会是孪生兄弟般的存在,再进一步推断是否会存在IRepositoryFactory 和 IUnitOfWorkBuilder 呢? 那么就可以带着这些问题在类库中找答案。
通过IRepository我会可能会发现一大堆的Repository类,
如抽象类:EntityRepositoryBase, FiledRepositoryBase ,JSONRepositoryBase 等
具体类:BlogRepository, PostRepository, UserRepository 等
注:作为练习大家可以去下载我在NuGet上发布的一个名为 DotNetAge Document Storage 类库,里面就有Repository的实现
一但掌握了从接口看结构的方法,就可以快速地在无文档的情况下理解类库的核心与设计理念。
参考“最佳实践”
一般上来说,流行的语言都会提供官方的“最佳实践”提供下载学习。这是一个必修项目,同一个需求,我们可以采用各种的设计方法来实现,但哪一种最好的? “最佳实践”就提供了方法选择的指导。“最佳实践”会有大量文档辅助讲解,在此时使用上述两个方法去学习那将会更大地提高你在设计上的提升。
随着不断的积累与大量的代码阅历,你可能就会得到这样一种能力:随便拿个Dll,在一个短时间内你可以如数家珍般说出整个Dll中的特点与功能。
这,就是“看”的练习方法,与练习后的效果
学
要成为架构师就需要突破语言的障壁,不同的语言有不同的优势,设计应该是因势利导,好的架构可用任何语言实现,反过来优秀的架构则应尽可能地发挥语言的特性。应用此方法前首先你至少已掌握或精通一门语言。
学习多种语言的动机
- 开拓视野,从不同语言中学习特有的设计理念
- 寻找与更新自己的 “最佳实践”
- 规避语言被淘汰的风险
开拓视野
我最近在不少网站上看到这样的一种论调:“学语言只学一门就好,不需要多只需要精”。咋一看,似乎是对的,而我认为仅限于初学者或不求进取者。这是一种语言同质论,是一种误导与限制!如果学习语言能“窥一斑而见全豹”那就不需要有那么多的其它语言存在了,对吗?
当对某一门语言精通(我指的是精通类库而不是语法)后,这个时间大概也得几年,很容易进入到一种“思维定式”,以某种固定语言为基点想问题,或是设计。一旦进入这种状态也就意味着局限性的出现,程序员或是架构师就被限制在了一个局部的小范围,而且还是风险极高的范围内。
IT的发展是飞速的,今天的宠儿明天的乞丐这种剧目屡屡上演着,你愿意被大浪淘沙吗?吊在一颗树上真是一条死路,这是技术发展的风险层面。又,你的设计工作对你还有挑战性吗?你是否仍然对设计和开发充满激情?你的设计是否在当下可以有什么让你自豪的特色或创建呢? 被同质化后这些答案都会被否定掉。
我的论点是:不断学习各种语言,体验各种语言所带来的开发与设计的激情,开拓自我的视野才是一个架构师应走的路。架构师不单单是技术的选择者,而更应该是技术的整合者。
选择“最佳实践”
我们长期会在某一领域内工作,自然而然会诞生出对此领域内的软件的设计理念与实现方法。但这仅是一种,举一个最简单的例子,同一个网站我们可以用ASP.NET MVC , Java, PHP 或是NodeJS来实现,固然实现方法与代码量就截然不同了。随便写个博客网站就能体验他们的区别所在:
- ASP.NET 和 Java的思维方式与代码量差异不大,学习曲线最长、 Hosting 资源成本中等,但数据库Hosting成本高
- Php 相对前两者简单而且资源众多,Hosting 资源最多,成本最低
- NodeJS性能最高、学习曲线最短、代码量最少、资源也最多但Hosting 成本最高
从这个比较中可见,作为架构师不单要考虑设计方法与实现,还得考虑部署环境。如果只是某一方面的“能手”那只能干瞪眼,无可选择。
我不是要选择“最好”的而是要选择“最合适”的,因时制宜,因地制宜才是我们所需要的“最佳实践”
成为 “O” 型架构师
开发是一个团队共同完成的,与真实社会一样,活在哪里就说哪里的话才会深入了解对方的文化。 架构师不是一个独立的个体,而是团队中不可或缺的成员,在行政与地位上与其它成员是对等的。开发队团就像是一个人,流着共同的血液。一个架构师,一份设计就应该是一种“O”型血,无论在哪个队团内都能融合,使用哪种语言都能实现与优化这才是一个好架构师的目标。
学习多种语言的方法
学习语言的方法大家都会有各自的路径与方法,在这里我只是介绍一下我自己的学习方法仅供大家参考与给我建议。我从业也10多年了,经历了不少语言以下这些是一些记忆与状态:
- Delphi (1-5) (Object pascal) - 这是初恋 , 拥有最多的界面组件和最简单的可视化开发环境,VCL算是当时最好的选择。
- VB (2-6) - 最容易调用COM的语言也是做面向对象很苦B的一个了。
- C++ - 学得最差的
- java - 用来学面向对象的
- C# - 算是我最擅长的,也是做项目最多的
- Php - 只能算是懂一点
- javascript - 我最喜欢的动态弱类型语言。
- css/less - 最让我头疼 (有了Less会好一点)
- html/xml/xslt - 最容易建立方法论的标记性语言是最容易建立发散性思维与抽象思维的工具
- Objective-C 和 Swift - 现在在学的
每一种语言就像自己的女朋友一般天天在身边陪伴着我们,所以想学得快首先是爱上她。即使她不再受宠也她会给我们留下很多美好的记忆。
感性认知
我学语言的第一步是不看语法的,因为面向对象的语言语法上基本是相似的,而且语法参考会很长读起来慢(这跟找老婆不要光看外貌是一个理)。我是从类库入手的,从主打的类库中可基本上快速了解整个语言的重要特色和常用的内容。就如iOS吧,一入手我会先看Cococa Layer中的UIKit,花两小时看完就知道XCode怎么用了然后就可以做个简单的移动应用跑一下,从感性上互相认识一下。
相互印证
没有哪个语言是没有参照物凭空发明出来的,就像学java时如果学过c++会很快因为java就是在极大层面上改进C++而来的,学C#的时候学过java就一下能上手,因为C#是微软没买到java自己搞出来的同时也去改进了java。所以语言之间会有互通性存在,在学习的路径上可以先了前他们的前辈是谁,有什么特色通过双向的印证了解可以很快速地去掌握与深入理解一门语言。
长年的积累
掌握一门语法很快,精通一门语言就是硬功了。这和我们学自然语言一样,词汇量是日积月累的成果。开发语言的词汇量就在于类库了,每一门语言的标准类库也是够我们喝一壶的,需要实践、学习与理解结合经验沉淀成我们的成果。在这方面我给出的建议就是要培养自己的耐心与毅力,罗马不是一天建成的,高手也不是一天就能修炼出来的。除了掌握官方类库还得将业界流行的类库和框架都能了解与熟悉这才算是“精通”。
写 - 疯狂的编码
“实践是检验真理的唯一标准” 能说不如能写。学到的知识是别人看不到的内容,作为程序员或是架构师将脑中的精华程序化呈现,然后成为产品这才是我们的终极目标。
学会一门语言并不代表写得好,作为一名架构师写的代码要求更是不同:
- 易读 - 命名是否符合代码规范,所有接口是否全部代码都有注释
- 易用 - 每一个类,每一个方法都是架构师与程序员的UI,少参数,容易理解的设计可以大大减少沟通成本。
- 框架化 - 一个一个类写是很慢的事,要活用模式于代码中能同时构建出10几个或几十个类。
- 参考性 - 架构师不是程序员,写代码为的是固定核心功能与公共用法,便于成员开发。面对复杂的场景需要多写示例同时也是测试设计的易用性的方法。
怎么才能达到这样的标准呢?
- 为自己立项从现在起为自己而编码
- 多写代码片 - 对局部的理论进行实践,多写一些小的代码片段或实验程序,而按正式项目一样来对待。完整的记录,共享源码获得Feedback,有良好的注释。
- 模仿是学习与理解新事物的最佳捷径 — 可以去仿造某些项目,当深入其中可以更直接地理解设计者的最初设计想法,同时也可以得到一个仿造品(不是抄,仿造的目的是获得编码经验)
- 尝试使用模式并控制类的规模
最后也就是时间的积累,疯狂地编码。同样的时间一个架构师的编码能力至少需要同等于五个以上程序员同时编码。
小结
架构师之路是一条很漫长而且需要不断学习、思考与实践积累的道路。我只是走了这条路的一小段,以此总结与更多的朋友分享共勉。在下一篇文章中我将会从另一个角度来谈架构师的修改项目:表达力。希望有兴趣的朋友能给予更多的关注与反馈。