Tagged: Design Toggle Comment Threads | 键盘快捷键

  • Roger 10:26 pm on September 16, 2011 固定链接 | 回复
    Tags: Design,   

    新工作一年回顾 

    不知不觉到新公司已经满一年了,回想一年前,自己的确做出了一个重大的决定,而从目前来看,这个决定还是相当正确的,当前的工作比较符合自己的期望,未来职业的发展也有更多空间。

     

    回顾这一年,自己在技术方面提高较多的方面包括:

    1. 对GUI框架设计和实现的理解 —— 在UC的这一年里面,大部分工作都跟GUI框架的设计和实现有关。刚进公司的第一件比较重要的工作就是为J2ME平台设计一个类似Android这样的现代GUI框架,虽然最后没有用于实际的产品,但是自己还是从中积累了很多经验,不但在设计和实现的过程中参考了Qt,Android,LWUIT等框架,同时也加入了很多特有的设计。在转到UCMobile后,大部分工作也是跟GUI框架里面的重要模块有关,包括动画框架,样式引擎,布局引擎等等。
    2. 对系统设计的理解 —— 因为有很多机会进行底层和中间层的系统和模块设计,感觉自己对系统设计的理解又提高到了一个新的层次。尤其是设计时需要考虑很多额外的约束,包括需要考虑J2ME平台本身的性能和内存耗费的限制,或者需要考虑兼容UCMobile原来的GUI框架等等,在这么多林林总总的约束下进行设计,迫使自己不得不绞尽脑汁如何在诸多因素中取得一个较好的平衡,从而极大锻炼了逻辑推理的能力,能够对一些设计中的细微之处把握的更精准,对模块之间依赖关系的掌控也更加得心应手。
    3. 对浏览器相关技术的掌握 —— 虽然自己一直在做浏览器产品的开发,但实际的工作跟浏览器核心的部分交集较少,不过也对相关的技术,包括HTTP协议,HTML规范,CSS规范,客户端JavaScript编程等多多少少有所了解,业余的时间也研究过一下WebKit的源码,特别是CSS的部分,因为实际的工作中实现过一个CSS解析器,所以这一部分了解比较深入。

    未来需要提高的部分:

    1. GUI框架仍然是一个飞速发展的领域,特别是在以下两方面 —— 声明式UI(使用脚本描述界面,使用JavaScript处理事件),和GPU硬件加速。自己在这个领域仍然有很多需要学习的东西。
    2. 浏览器核心,毋庸置疑,这部分技术价值含量高,而且发展十分迅猛,即使在实际工作中缺少机会,自己仍然需要更多利用业余时间进行学习和实践。
    Advertisements
     
  • Roger 3:33 pm on September 14, 2011 固定链接 | 回复
    Tags: Design   

    两个系统的故事 

    前一段时间,我写了一篇文章“碎片化系统”,表达了自己对参与的两个十分混乱的系统的一些感想。刚好前几天看了“架构之美 Beatiful Architecture”一书,其中的第二章“两个系统的故事:现代软件神话 ”,也表达了同样的想法,而且说的更加清晰明了。这一章的部分内容摘要如下(InfoQ出了一本迷你电子书,可以在这里下载):

     


    两个系统的故事:现代软件神话

    Pete Goodliffe

     

    软件系统就像一座由建筑和后面的路构成的城市—由公路和旅馆构成的错综复杂的网络。在繁忙的城市里发生着许多事情,控制流不断产生,它们的生命在城市中交织在一起,然后死亡。丰富的数据积聚在一起、存储起来,然后销毁。有各式各样的建筑:有的高大美丽,有的低矮实用,还有的坍塌破损。随着数据围绕着它们流动,形成了交通堵塞和追尾、高峰时段和道路维护。软件之城的品质直接与其中包含多少城市规划有关。

     

    某些软件系统很幸运,创建时由有经验的架构师进行了深思熟虑的设计,在构建时体现出了优雅和平衡,有很好的地图,便于导航。另一些软件系统就没有这么幸运,基本上是一些通过偶然聚集的代码渐渐形成的,交通基础设施不足,建筑单调而平凡,置身于其中时会完全迷失,找不着路。你的代码愿意待在怎样的“城市”中?你愿意构建哪一种城市?

     

    在本章中,我将讲述这样两个软件城市的故事。这是真实的故事,就像所有好的故事一样,这个故事最终是有教育意义的。人们说经验是伟大的老师,但最好是别人的经验,如果你能从这些项目的错误和成功之中学习,你(和你的软件)可能会避免很多的痛苦。本章中的这两个系统特别有趣,因为它们有很大不同,尽管从表面上看非常相似:

          •   它们具有相似的规模(大约500 000行代码)。

          •   它们都是“嵌入式”消费音频设备。

          •   每种软件的生态系统都是成熟的,已经经历了许多的产品版本。

          •   两种解决方案都是基于Linux 的。

          •   编码采用C++语言。

          •   它们都是由“有经验的”程序员开发的(在某些情况下,他们本应知道得更多)。

          •   程序员本身就是架构师。

     

    在这个故事中,人名都已改变,目的是保护那些无辜的人(和有罪的人)。

    (More …)

     
  • Roger 10:35 am on May 21, 2011 固定链接 | 回复
    Tags: Design   

    碎片化系统 

    进入新公司也差不多超过半年的时间了,在这段时间中参与了两个不同产品的开发,这两个产品的系统设计取向虽然截然不同,但是都呈现出类似的状况,就是系统的杂乱无章和碎片化。

    中间层

    如果把应用所处的平台和基于的应用程序框架(如Android Runtime)当作系统的底层,应用所包括的各项功能实现的集合当作系统的上层,通常我们还需要一个所谓的中间层,这个中间层可以起到的作用包括:

    • 为跨平台的应用构造一个隔离层,自身可以适配不同的平台;
    • 对平台本身的一些模块进行封装和增强,解决系统兼容性问题,增加应用所需的功能;
    • 从应用所包括的各项功能中抽取通用的逻辑,为功能的实现提供强有力的支撑;
    • 为各个功能模块提供各种管理,数据传输和通讯服务;

    碎片化

    一般而言,如果是不太复杂的应用,本身又基于一个比较成熟的平台和应用程序框架,对构造一个中间层的需求并不大,大部分情况下都可以忽略掉。但是很不幸,上述的这两个产品由于自身的复杂性,或者由于所处的平台,或者由于技术方案的选择,都要求必须要有一个强有力的中间层作为支撑,而缺少这样一个设计良好的中间层,导致了上层的各个功能模块都不得不为本来应该是功能无关的通用逻辑提供自身的实现,而这些实现通常缺乏严谨的设计,并且大多为了赶工仓促而就。

    总之,这使得整个系统充斥着大量这样的小模块,它们相似但又不完全相同,设计蹩脚,实现粗糙,很多明显残留从别的地方把代码拷贝过来然后进行修改的痕迹。各个功能模块之间缺少一个统一的中间协调者,不得不自己直接跟其它模块交互,系统的相互依赖性和耦合度轻易就泛滥到无法收拾的地方。

    这样一个系统就像是由一堆碎片拼凑堆砌而成,为了整个系统不至于散架,还需要淋上一打胶水把这些碎片紧紧地粘合在一起。随着功能的增加,系统的复杂度的增长,这个系统越来越变成像是一个吞噬工程师血汗的怪兽。每一次修改,常常都波及大半个系统,每一个功能的增加,都像是要在这一堆粘的密密实实的碎片中撕开一道裂缝,然后再把自己硬塞进去。每一个身处其中的工程师都苦不堪言,咒骂着参与制造这样的怪兽的人,然而他们自己也将在不久的将来成为后续维护这个系统的工程师咒骂的对象。

    成因

    考究这样系统的成因,可以大概归为:

    • 缺少一个有经验的系统设计师在开始作出一个完善的全局设计,并在后续的演化中维护这个设计的基本架构;
    • 产品的开发以功能实现为导向,工程师只追求尽快实现功能,而无法做更长远的思考;
    • 没有分配工程师专职于系统中间层的构建,所有工程师都忙于于功能的实现和bug的修正;
    • 一些较为有经验的工程师会试图抽取一些可复用的代码,但是因为这些代码还是直接跟具体的运行上下文绑定在一起,并且API也不完备,缺少良好的文档,最终还是仅仅停留在只能供自己使用的程度;
     
    • chdz 2:40 下午 on 五月 21, 2011 固定链接 | 回复

      呵呵,确实如此。 都是边学边做,对知识半懂非懂赶上架。对手机知识的通晓的人少又少。

  • Roger 8:44 pm on May 2, 2011 固定链接
    Tags: Design, , Java 2D   

    把大象放入冰箱与设计抽象性的思考 

    Q:如何把大象放入冰箱

    A:把冰箱打开,然后把大象放进去,再把冰箱关上

    当然这是一个脑筋急转弯的笑话,但是对于系统设计者的启示是,如果你设计了一个足够抽象的接口,理论上这个接口可以代表近似于无限的实现,简单的说越抽象的接口,它可以衍生出来的实现就越多。

    如果我们把上面的问题当作一个软件功能上的需求并对它进行建模,我们可能会推导出下面的UML模型:

    Elephant

    在上图中,接口Containable和Placeable表达了两个非常抽象的概念,一个代表可以放置Placeable的容器,一个代表可以放入Containable的物件,而类IceBox和Elephant 分别实现了这两个接口。

    如果用代码来表示把大象放入冰箱的过程,可能的代码如下:

     1: void placeElephantInIceBox(IceBox box, Elephant e)
     2: {
     3: 
     4:     box.open();
     5:     box.place(e);
     6:     box.close();
     7: }

    上面的思考主要是受最近在看的Java 2D Graphics一书的启发,Java 2D是Java提供的2D Graphics Library,它是一个全功能,桌面操作系统级别的2D绘图库,为了能够在实现复杂功能的同时保有一个尽可能简单的编程接口,并且允许用户继续对它进行扩充,Java 2D提供了一个高抽象度的模型,很多接口的抽象度基本就跟上面的Containable和Placeable类似。

    比如说Stroke接口代表了笔画,但是它实际上是将一个输入的Shape转换成根据该笔画描绘出来的轮廓的Shape(Java 2D只处理图形填充,所谓描绘图形的轮廓实际上是先生成图形的轮廓图形,然后再对该轮廓图形进行填充)。

    下面的代码基本等同于直接调用Graphics2D中的draw(graphics.draw(shape);):

     1: void drawShape(Graphics2D graphics, Shape shape)
     2: {
     3:     Stroke stroke = graphics.getStroke();
     4:     Shape strokedOutline = stroke.createStrokedShape(shape);
     5:     graphics.fill(strokedOutline);
     6: }

    其中createStrokedShape就是Stroke接口的唯一的方法。

     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
回复
e
编辑
o
Show/Hide comments
t
返回顶部
l
Go to login
h
Show/Hide help
shift + esc
取消