HYXT Blog

we produce valuable software for K12.
clock September 16, 2009 23:58 by author Sky Jia (贾超)

clock April 14, 2009 13:54 by author Sky Jia (贾超)

According to the Cambridge Dictionary an apprentice is "someone who works for an expert to learn a particular skill or job". Merriam Webster says: "one who is learning by practical experience under skilled workers a trade, art, or calling". Uncle Bob Martin recently wrote about his experience with apprentices and what he considers key to progressing from apprentice to journeyman.

He describes two hypothetical apprentices: Sam, a developer who has apprenticed with the same master and had the same year fifteen years in a row. The other, Jasmine has changed jobs (and therefore masters) a number of times - growing her skills along the way. The following diagram illustrates the difference in their progress.

Bob’s point is that Sam, who has never changed masters, will always be a student and his growth is limited. Whereas Jasmine, who’s path has been varied,  really is a journeyman – travelling from master to master learning new things from each. Eventually Jasmine herself can become a master.

One commenter JMiller suggests that with a large enough company that you don’t need to leave your employer to change masters companies the size of Google or Microsoft, etc.

Corey Haines points out that while there are companies that are large enough to support Journeyman tours inside the company, none that he knows encourage it.

From her experience at Tektronix, Rebecca Wirfs-Brock remarks: “To me, moving around in the same company is roughly equivalent to changing employers, especially if the company is big enough…and I did several job shifts in my 13 years at Tektronix.”

Corey Haines is starting to have some ideas about how one transitions from apprentice to journeyman:

During the apprentice phase, a person is busy learning. They are practicing specific techniques, rigorously applying rules and procedures. Over time, having been influenced by many mentors, an apprentice starts to develop their own toolbox, the set of practices that they systematically apply. These practices form a basis for further development, a core that an apprentice can build upon.

Paul reports that in the UK companies use a similar approach hiring and training mechanical apprentices. After 6-12 months the apprenticeship is complete and people often move on somewhere else in the industry. Even though the company may not retain that person they benefit as they have a larger pool of well trained people to hire from in the future.


clock March 12, 2009 18:21 by author Sky Jia (贾超)

作者 章昱恒 发布于 200935上午1230

数据迁移是指在系统软件开发中,将具有实际业务价值的数据,依据功能需求或系统开发的要求,在不同存储媒介、存储形式或计算机系统之间转移的过程。

数据迁移是系统开发经常涉及到的一项工作。在企业级应用系统中,新系统的开发,新旧系统的升级换代,以及正常的系统维护,不可避免地涉及到大量的迁移工作。而在一个以数据为核心的业务系统中,数据的迁移更是无处不在。比如:在以数据仓库为架构原型的系统设计中,ETL(抽取,转换,装载)部分的实现就是一种数据迁移;对大型数据系统的分布式实施,数据迁移就是整个实施过程的主要部分。而在敏捷实践中,渐进式的数据库开发,更是涉及到大量的数据迁移和同步工作。

我们时常会听到用户提出这样的要求"我们并不过于关心应用的好坏,但需务必保证数据准确"。的确,在以数据为运营基础的行业里,数据质量本身就是软件质量的权重部分,尤其在电信、金融和控制领域里,这一特征表现的格外明显。数据迁移也是敏捷开发中相当重要的环节,它影响着各个发布版本的数据质量,而数据质量又决定着系统的有效性和可靠性,因此高质量地完成数据迁移不容忽视。

数据迁移往往被视为一件很简单的工作。在很多人眼里,数据迁移仅仅是用sql语句向相应数据表装载数据的过程。但在实际操作中,数据迁移涉及到很多层面的因素,如用户需求,系统功能,数据库建模等,若出现问题,将导致开发进展缓慢或质量不高。常见问题有业务系统逻辑模糊、脏数据、遗留系统的技术债和管理债等。那么如何有效的避免这些问题,提高迁移质量呢?

本文将以ThoughtWorks中国公司与客户合作的CRM项目为背景,为读者介绍如何在敏捷开发中高质量地处理数据迁移工作,从而在数据层面提高系统质量。

开发背景

A系统(旧系统)是客户原有的一套CRM(客户关系管理)系统。系统采用B/S 架构,使用sql server 2005做为后台数据库。旧系统的数据建模设计采用了高度范式化的设计思路,其目的是极度追求灵活性。业务数据被大量拆分并散布存储在上百张数据表里。数据表内和表之间不存在参照约束。大量的业务逻辑采用存储过程封装以提高效率。存储过程体系相当庞大,且存在复杂的相互调用。数据库中存在一些脏数据,可能是长期的使用、维护或误操作导致,但没人知道它们有多少,具体存在哪里。应用界面可用性不理想而且系统效率较低,用户常抱怨系统反映迟缓或无反应。数据库存储的业务数据约50G左右。

ThoughtWorks 团队将为客户提供一套新的CRM系统用以替换旧系统主要功能。新系统精简整理旧系统功能,并整合了客户的最新需求。在设计上做了巨大变更,以改善界面可用性,同时为了保障终端用户对系统服务的需要,新旧系统要求能够同时运行并实现数据同步,当终端用户全部过度到新系统后,终止旧系统。在这个过程中,DBA 团队需给予足够的数据保障。

以下为项目版本的发布图。

数据迁移开发方法

1. DBA需要制定目标并且管理自己的任务

尽管在每个迭代中,团队都会讨论决定如何组织'需求故事'story),但是DBA仍然需要有自己的'故事墙'story wall),并且花时间组织自己的story。在实际开发中,数据迁移仅仅是DBA工作的一部分,DBA还要完成相应的story开发和数据分析,有时还要给开发人员提供数据支持。混乱的管理会带来开发上的冲突。因此,有效管理任务是做好数据迁移的首要环节。

故事墙是管理这些任务的最好方法。尽管这个故事墙对客户提供的商业价值是间接的,但从整个团队角度来看,任何需要数据的人或程序都是DBA的用户,故事墙有利于管理每个story包含的数据需求,避免数据迁移任务与其它数据库开发任务之间的冲突,从而减少重复性工作或修复性工作。DBA有必要将这种方法引入到数据库开发中。

DBA要从商业价值角度决策数据迁移的需求。系统开发中,客户和开发员常常会向DBA提出自己的数据迁移要求,但往往这些要求并不具有全局性和决定性,毕竟他们仅仅是针对一个story的需要而提出。如果DBA盲目执行,将起到事倍功半的效果。DBA应当积极参加IPM(迭代计划会议。它是在每个迭代开始时的会议,全体成员共同讨论story计划完成数量)。无论是直接与用户交互,还是参与团队合作,DBA有必要将每个story内容了解的清清楚楚。通常,DBA可以不必像开发人员一样去了解story的开发细节,但通过与业务分析师和开发员的沟通,潜在的数据需求自然浮出水面。针对这些数据需求,通过再次组织并加以优先级,我们很容易回答这些问题:接下来应该完成的任务是什么?它的实际商业价值是什么?谁将需要它?什么时候需要?实践证明,多花些时间和团队或客户沟通是事半功倍的好方法,而且DBA通过了解业务数据可以给开发员更好的指导,减少开发员对数据的误解,有利于提高整体团队的开发效率。

通过对每个story的了解,我们总结并制定了针对当前发布版本需要的7个数据迁移story,并且确认了它们的确不存在任务上的重复,也邀请项目经理和客户一起确认了这份计划。如此我们的目标已经制定。

2. 思考实施策略

我们已经管理好所有数据迁移的任务,接下来考虑如何实现。通过以往的经验,我们发现如果没有仔细思考全局和细节问题而直接编写代码,带来的后果是无法控制的。我们应该首先充分了解这个过程可能存在的风险,然后决定采用什么样的策略,是否可以借助工具提高效率。这里的潜在风险主要包括:

2.1 数据质量

旧系统的数据库建模是一个高度范式化的结构,每个表之间存在相当大的依赖关系。一旦一个表存在脏数据,我们如何保证得到正确的查询结果?

2.2 对原有系统的了解

旧系统的应用程序引入了面向对象的设计方法,并且继承关系数据也被存储在若干张数据表里,如何正确区分这些业务对象和关系,保证在迁移过程中不会制造脏数据?

2.3 业务数据映射

旧系统和新系统之间存在着相当大的业务逻辑差异,我们是否能够将业务逻辑、数据映射到新系统?是否存在不可实现的转换?

在未充分了解这些问题之前,我们无法进一步制定计划,即时给予客户反馈是解决这些问题的最好方法。经过进一步沟通后,我们发现问题的复杂程度远远超过想象,尽管客户对旧系统非常了解,但他们对于某些数据也不能给出明确答案。鉴于这些情况,我们制定了初步的解决策略:

  1. 更多的了解旧系统,即时给予反馈。对于那些无法找到答案的问题,考虑是否可以寻求其它资源或忽略没有价值的数据。
  2. 尽量细化分割每一个复杂需求,形成多个任务。小粒度任务能够帮助暴露更多问题。
  3. 采用测试驱动,确保一套可靠的测试机制。
  4. 制定实现框架和阶段性目标。
  5. 不要过于乐观的估计进展,每一阶段要留有充分的单元测试。
  6. 调整每个迭代的内容,对有较强依赖关系的任务可以放在今后的迭代周期里。

3. 实施数据迁移

新系统的数据迁移包含两个部分:一次性数据迁移和数据同步迁移

一次性数据迁移

一次性数据迁移指仅仅发生在某一个发布版本上线安装时,新旧系统同时处于脱机状态,一部分数据将从旧系统中转移到新系统的过程。

数据同步迁移

数据同步迁移过程发生在新系统运行时,新旧系统同时处于工作状态,双方通过交换数据保证彼此数据的一致性。

同为数据迁移,但因两类迁移各具特点,因此在共同的处理方式上也略有不同。

  

一次性数据迁移

数据同步迁移

特点

  1. 数据量大。
  2. 使用频率低(一次性使用)。
  3. 转换逻辑复杂,需大量定制映射转换数据。

  

  1. 数据量小
  2. 使用频率高(以分钟为单位,周期性运行)。
  3. 转换逻辑复杂,少量定制映射转换数据。
  4. 需要事务处理以保证数据一致性

共同处理方式

  1. 细化任务。
  2. 测试驱动。
  3. 持续集成

不同处理方式

  1. 在执行测试驱动中,应侧重数据质量的测试。应依据不同环境的测试结果,增强测试体系。
  2. 工具选择。避免使用第三方工具,直接使用sql脚本以提高迁移效率。
  3. 保留中间处理结果
  1. 在执行测试驱动中,应侧重逻辑映射方面的测试。
  2. 工具选择。可考虑使用第三方工具,增强事务控制。
  3. 可不保留中间结果
  1. 细化任务

依据最初制定的开发策略,当我们遇到复杂的迁移需求时,首先分解每个需求为若干个模块,然后画出整体结构图。以下是某一处数据迁移脚本的模块分割:

最初由于这个部分的迁移逻辑过于复杂,以至于客户对它的处理结果没有信心。但当共同完成这个图表后,大家一致认为它没有像想象中的困难。总而言之,立刻解决一个复杂的问题很困难,但解决其中一个小问题却很容易。

  1. 测试驱动

如同编写程序代码一样,我们不仅为实现数据迁移脚本使用了测试驱动,还引入了针对数据库设计的一些方法。在程序设计中,当代码本身结构良好,单元(类、方法)之间关系清晰,可以直接添加单元测试。现在,我们有了很好的脚本逻辑结构,可以很容易添加每一步结果的单元测试,这就如同形成了一道安全网,保证异常数据出现时,能够立即发现并加以处理。在实际编写迁移脚本之前,应首先明确测试内容,准备好测试脚本。

测试内容包括:

  • 应产生的符合期望的数据

基于给予的原始测试数据,这一测试过程测试脚本的数据转换逻辑是否正确。以下举例说明:

测试环境:旧系统中存在某个名为'Jason'的客户信息,他的personId 1000101

测试目的:当某一客户的信息迁移到新系统的CUSTOMERS表后,新系统应该存在该客户信息。

新系统上要运行的测试代码:

DECLARE @personName NVARCHAR(250),

  

SELECT

@personName = personName

FROM

CUSTOMERS

WHERE

personId = 1000101

 

IF (@personName <> 'Jason') or (@personName is NULL)

BEGIN

INSERT INTO LoadTestErrorLog (errorDescription)

VALUES ('personName for personId 1000101 is not Jason')

END

Go

 

这里常用的原则是:一段sql语句仅用来测试一处期望数据,这样可以减少代码之间的相互依赖性,更准确的定位错误数据。

  • 不应当产生的异常数据

异常数据指在迁移过程中出现的不符合逻辑的数据。理论上讲,迁移过程不应当出现异常数据,然而现实情况中,迁移结果总会出现我们不需要的数据。其原因包括数据源出现异常、实现过程中的误操作、系统应用的bug等。总而言之,为了保证这些错误不会出现在最终结果,相应的测试脚本必不可少,也是防止问题进一步扩大的有效举措。这一测试过程常被用来发现在生产环境中可能出现的问题。以下举例如何测试异常数据:

测试环境:全部或部分生产环境数据

测试目的:将某个客户的信息迁移到新系统的CUSTOMERS表后,数据表不应该具有顾客名字为空的记录,如果出现将视为迁移过程的错误。

新系统上要运行的测试代码:

DECLARE @isExistPersonNameWithNULL INTEGER

  

SELECT

@isExistPersonNameWithNULL = count(*)

FROM

CUSTOMERS

where personName is null

  

IF (@isExistPersonNameWithNULL> 0)

BEGIN

INSERT INTO LoadTestErrorLog (errorDescription)

VALUES ('personName doesn't contain legal information')

END

  

Go

  • 数据表的数据量是否符合期望

当数据被迁移至新系统后,应当确保迁移数据量符合应期望值。实现方法多种多样,较简单的方法是直接比较数据迁移前后的数据记录数是否在数值上相等。以下举例说明:

测试环境:全部或部分生产环境数据。

测试目的:客户数据被迁移后,应当确保客户数据没有丢失。

新系统上要运行的测试代码:

DECLARE @NumberofCustomerinOldDB INTEGER

DECLARE @NumberofCustomerinNewDB INTEGER

  

SELECT

@NumberofCustomerinOldDB = count(*)

FROM

oldDB.dbo.persons -- 这是在旧系统中定义的客户表

...

--省略复杂的过滤逻辑

SELECT

@NumberofCustomerinNewDB = count(*)

FROM

newdb.dbo.CUSTOMERS -- 这是在新系统中定义的客户表

where personName is null 

 

IF (@NumberofCustomerinOldDB<>@NumberofCustomerinNewDB )

BEGIN

INSERT INTO LoadTestErrorLog (errorDescription)

VALUES ('not all customers are migrated ')

END

Go

 

最终当把测试sql代码片段组装在一起后,我们获得了一批测试脚本,并按照以下流程,通过使用NANT工具实现自动化:

NANT中的实现方法:

<target name="-init " … />

该任务负责初始化测试环境

<target name="-parseDbScripts " … />

该任务负责编译并部署迁移脚本

<target name="-resetTestData " … />

该任务负责重置测试数据

<target name="-executeMigrationScripts " … />

该任务负责执行迁移脚本

<target name="-testMigration " … />

该任务负责执行迁移测试脚本

<target name="testDataMigration" depends="-init, -parseDbScripts, -resetTestData, executeMigrationScripts, -testMigration" />

该任务将成为持续集成调用的入口

  1. 持续集成

为完成持续集成测试,测试沙盒必不可少。"沙盒"是一个完整的功能环境,在这里脚本能够被编译,测试和运行。

  • 在开发沙盒中,我们准备了少量的核心数据,用以测试sql脚本的质量。
  • 在系统级集成测试沙盒中,我们还准备了一个小型数据库,这个数据库包含了一部分核心数据,着重测试数据迁移过程的逻辑转换。
  • 在生产环境级测试沙盒中,由于数据库来源于实际数据备份,因此数据处于不断变化状态,这就更需要不断运行测试脚本,避免脏数据和数据丢失。由于生产环境数 据量相对大了许多,我们可以适当减少测试次数以减少对开发资源的消耗。同时,其它测试脚本,如变更数据库结构的脚本,都可以和数据迁移脚本组织在一起,一 次性完成测试。

    同样,我们采用自动化机制维护这些开发测试沙盒。

    将测试置于持续集成环境中,下图是处于持续集成环境的测试任务。

  1. 工具选择

选择数据迁移工具应当以帮助提高工作效率和数据迁移运行效率为原则。通常最直接的方法是编写sql脚本,借助其它工具也能起到很好的效果,比如MS SSIS等。然而我们发现,过多的引入第三方工具往往带来的麻烦也多,例如,我们不得不花时间来学习这些工具的某些特殊用法,有时工具也会产生bug,以至于不得不再花时间解决这些bug,而这与最初的开发目标相背离。因此,有效的方法是尽量使用sql脚本执行所有的迁移工作,同时也得到了最佳的执行效率。

  1. 保留中间结果用于脚本调试

相比设计语言,Sql语句较难调试,即使有些数据库产品提供了调试工具,但是调试数据结果集仍然是项挑战性的工作。尤其在旧系统到新系统的迁移过程中,业务逻辑发生巨大变化,客户经常要求提供某些证据,来解释他们对数据迁移结果的怀疑。保留中间环节数据,不仅方便调试,也方便数据追溯,为开发带来更高效率。以下举例说明:

SELECT

...

into debug_allpersonhistroy

FROM

oldDB.dbo.personhistory -- 这是在旧系统中定义的业务存储表

...

--省略复杂的过滤逻辑

select column1...columnN

into debug_allpersonhistroy_aftermapping --保留这一步数据集合

from debug_allpersonhistroy inner join mappingtableBtwOldandNew

...

--省略复杂的过滤逻辑

SELECT

...

FROM

newdb.dbo.contactHistory -- 这是在新系统中定义的业务存储表

...

--省略复杂的过滤逻辑

Go

典型问题

数据迁移在不同的场景往往出现不同的问题,单凭经验也不能全部解决。运用头脑风暴,集中团队中所有力量思考所有可能出现的问题并加以避免。有时开发员遇到的问题也帮助DBA少走弯路。最终,头脑风暴能够提供我们的是一份有价值的列表,里面包含各种问题和注意事项:

  1. 一致性检查

一致性检查包括:字符编码检查、语言设置、环境参数设置等。

迁移过程常出问题的是字符集,它带来的问题是数据乱码。不同系统在最初设计时应用的字符集或编码格式未必相同。在迁移过程中,单凭缺省设置是不够不安全的。有效的办法是在项目伊始,即确认系统间环境一致性。在新系统中采用兼容性的unicode编码也能够解决这些问题。

  1. 控制NULL的使用

由于旧系统本身很少使用约束,以至于在表连接查询中出现大量无法得到正确匹配的数据。在 sql中,当我们试图使用自然连接,我们发现某些数据丢失了,如果使用外连接,这将会带来一种新的脏数据:NULL。从数据库设计角度,NULL不代表任何含义,而实际情况中,很多数据库建模往往给NULL赋予含义,甚至多种含义,以至于不同的查询需求要视不同的业务逻辑对待。在旧系统里,这种现象比比皆是,无疑给迁移带来了不少麻烦。

解决方法:不为NULL赋予逻辑上的定义。尽量少使用外连接运算。

例如:

旧系统定义如下父子结构表:

objectId, parentObjectId,objectType …

------------------------------------

Null Null 'root'

1 Null 'contactManager'

2 1 'contact'

3 1 'contact'

4 Null 'orgnisation1'

 

显然,系统希望构建如下对象树图:

然而,当程序试图遍历所有对象时发现:NULL无法参与计算。因为NULL与任何数据的计算结果都是NULL。程序必须增加额外代码来处理特殊情况。

  1. 代码复用,降低依赖性

迁移脚本应当遵循与编码同样的规则,高内聚,低耦合,能够被重复利用的代码需尽量被封装成单元,重复拷贝并不是迁移脚本应当采用的方法。

解决方法:使用临时存储过程实现某些公用代码的复用,简化调用接口。

  1. 新问题,新测试

当我们遇到新的问题时,常忙于解决问题,给出解释。然而当这一切完成后,并不意味着问题已经全部被解决。因为这些问题仍然可能再次发生,也说明目前测试不足。

解决方法:当新问题出现后,暂停当前的工作,立刻针对这种情况写出测试。为其花费些时间意味着不会让技术问题债台高垒。

例如:在新系统的数据库里,QA发现了一组不符合逻辑的数据:记录的结束时间(EndTimestamp)早于开始时间(startTimeStamp)8个小时。它的实际期望结果是:记录的结束时间必须晚于开始时间。

ID startTimestamp, EndTimestamp, createDate …

-----------------------------------------------------

11020011 2008-12-14 09:23:00 2008-12-14 01:23:00 2008-12-14 09:23:00

 

显然程序在插入数据时用错了时区。在bug被修复之前,立刻加入一个数据库测试以保障今后不会再次出现。

测试代码如下:

DECLARE @CNT INTEGER

  

select @CNT=COUNT(*) from tableA where startTimestamp> EndTimestamp

IF @CNT>0

BEGIN

INSERT INTO LoadTestErrorLog (errorDescription)

VALUES (' EndTimestamp should be late than startTimestamp ')

END

GO

  1. 目标制定者和开发者应该保留的心态

数据迁移是一件看似简单但具有挑战的工作。因此,我们常常过于乐观估计开发效率。然而这里的风险在于我们仅仅看到了处理逻辑,而没有看清楚数据质量,以至于盲目写出的迁移脚本可以在测试环境中工作,但无法在生产环境中运行。

解决方法:无论多么简单的数据迁移,应首先与客户或业务分析师沟通业务逻辑,确保对数据质量的了解。

结论

数据迁移是一项看似简单却蕴含巨大挑战的工作。它不仅包含了具体技术问题,而且要求DBA具有较好的沟通能力,深入的了解业务逻辑。通过旧系统到新系统的数据迁移工作,我们逐渐地将精益软件设计思想深入到细节,并且取得了很好的效果。当数据迁移完成后,我们完成了近6000行的迁移脚本,迁移结果通过了客户方的抽样测试,最终确保了整个系统的正常运行。


clock January 4, 2009 14:04 by author Sky Jia (贾超)

Project Time Management is one of the nine knowledge areas of the Project Management Body of Knowledge (PMBOK). It deals with the definition of activities (what are we going to do), the sequencing of the activities (in what order are we going to do them), and the development and control of the schedule (whenare we going to perform those activities).

Agile Time Management
Over the past couple of weeks I have been trying to find out what the main principles of time management are in the case of agile software development. I was able to distinguish 10 principles so far, and I will present them here for your convenience. With each principle I also include a reference to an online article that (as far as I can tell) nicely describes the ideas behind it. If you don't agree with my list, or if you know some better reference material, feel free to add your thoughts!

1. Use a Definition of "Done"
How? Define what "Done" means and only count the activities that are Done.
Why? Prevent the build-up of hidden tasks ("technical debt") that cost a lot of time to fix down the road.
SeeThe Definition of "Done"

2. Use Timeboxes to Manage Work
How? Set a start- and end date for a collection of activities, and don't allow changes to those dates.
Why? Timeboxes keep people focused on what's most important. Don't lose time to perfectionism.
SeeTime Boxing is an Effective Getting Things Done Strategy

3. Don't Add Slack to Task Estimates
How? Don't use scheduling and buffering of tasks. Add one buffer to the end of the timebox/project.
Why? All safety margins for tasks will be used ("Parkinson's Law" and "Student's Syndrom'").
SeeCritical Chain Scheduling and Buffer Management

4. Defer Decisions
How? Make decisions only at the latest responsible time. "No Decision" is also a decision.
Why? The environment may change, making earlier decisions a waste of time.
SeeReal Options Underlie Agile Practices

5. Reduce Cycle Time
How? Iterative cycles should be as short as possible.
Why? Speed up the learning feedback loop, and decrease the time-to-market.
SeeLean Software Development: Why reduce cycle-time?

6. Keep the Pipeline Short and Thin
How? Limit the amount of work-in-progress, and the number of people working in sequence.
Why? Improve response times, speed up throughput.
SeeManaging the Pipeline

7. Keep the Discipline
How? Prevent expensive rework by doing some processes well, right from the start
Why? Solving problems late in a project is more expensive than following proper rules early.
SeeThe Power of Process

8. Limit Task Switching
How? Prevent unnecessary task switching between projects, and prevent interruptions.
Why? Tasks get completed faster on average, and the human brain is bad at task switching.
SeeHuman Task Switches Considered Harmful

9. Prevent Sustained Overtime
How? Disregard (sustained) overtime as a way to accellerate progress.
Why? Lost productivity, poor quality and bad motivation among team members.
SeeThe Case Against Overtime

10. Separate Urgency from Importance
How? Urgent tasks and important tasks should not be done at the same time.
Why? The important stuff will usually not get done, costing you more time in the long run.
SeeA 10 Second Guide to Smoother Projects: Urgent vs. Important


clock December 3, 2008 19:06 by author Sky Jia (贾超)

 1. 谁是用户?

不应该只把用户定位为最终用户,对于开发一个产品来说,用户包括最终用户、开发者、主管、老板(投资方)、合作伙伴、商业用户等,也就是定义、开发、实现和运营产品所必需面对的所有群体。产品设计中的“设计”具有联系发展的特征,或者说包含设计本身及设计的传达和沟通,所以当你想实施“以用户为中心的设计”的时候,你需要考虑更多的用户,包括坐在你隔壁的伙伴,也就是除了你,其他相关人员都是用户。

2. 本身为谁设计?
回到产品设计本身,我们需要明白产品最直接面对的是谁,最终为谁设计,把矛头对准最终用户,这是产品的主线索也是传达和沟通的主线索,所以从头到尾,保持这个矛头。

那么首先要避免为自己设计,很多时候确实是这样,就算你不承认,虽然你的脑袋里也一直有用户,也明白应该为最终用户设计,但事实总是差强人意。作为设计或开发者,想要忽视自己脑袋里已经存在的认知和行为模式而使用另一个人(用户)的认知和行为模式,这确实很难,但可以通过新建一个记忆通道来更好的避免这个问题,从源头开始就不再是你,没错,就是用户角色的建立和完善,这可以在一定程度上解决错位的问题,这个记忆通道越饱满,就越不容易错位,设计的目的就越准确。

3. 最终用户是谁?
现在需要丰富和鲜活用户角色的一切,那就尽可能的先去了解用户群体,再从用户群体中归纳和总结,千万不要和需求脱离,用户和需求是什么样的关系?鸡和蛋的关系?不如理解为相互验证和制约的关系吧。按照书上说的从以下方法来分析:

  • 靠想象,依据个人的知识和经验、平时的观察体验和积累
  • 用户访谈、现场调查
  • 可用性测试
  • 用户调查
  • 网站流量/日志文件分析

但现实情况可能让你感到困难,发现除了第一条以外,其他的都没条件去做,这很糟糕。没关系,别忘了调动你的团队伙伴们,让他们一起参与,这绝对是件很有价值的途径。另外你必须学会怎么从同类或竞争产品吸取经验,关于这点,有以下一些建议:

  • 体验是一个体系,心智模型不只是征对某种服务,他具有某个或多个领域内的延续性。
  • 先学会做一个用户,保持热情并体验各种各样海量的服务,学会分析和总结。
  • 在比较成功的产品上多下点功夫,他们已经培养了很多用户的行为模式。
  • 在同类或竞争产品的范围上画个稍大点的圈,并尽量细心的使用和体验,做记录很重要
  • 把你的体验结果和经验跟你的伙伴们交流

4. 用户是不是把你带到了沟里?
现在你可能更了解用户了,或者你发现正被用户带到沟里,你的伙伴们也都开始抱怨了,还有比这更糟糕的吗?当然有,那就是到最后才发现被用户带到了沟里,应该说被你的用户带到了沟里,这真是莫大的挫折。原因可能有两个,一是你不了解用户,二是你不会使用用户。所以在你有一定的数据积累及证据呈现前,不要轻举妄动,应该扎实的学习和积累,并学会慢慢的渗透给团对,在整个团队之间引起共鸣和相互交流,这对你本身的提升是一个很有效的途径。谨记一条,多知道一点不代表你可以当专家。

5. 最终用户跟其他用户的关系
如第一点所述,除了最终用户,你必须直接面对一个相当数量的用户群体,这就要求你沟通和论证的角度各种各样,当然你会有很多的办法,比如三寸不烂之舌。再想想产品最终是为谁设计的,那么为什么不通过引入用户角色增强团队对以用户为中心的设计的理解和执行,并建立一个沟通的有效数据规范,而规范实际上就是共识的达成。

最后,不要为了建立用户角色而建立用户角色,还有用户角色不是名词,现在,你可以悄悄地去实验和执行以用户为中心的设计了,经过不断的失败,领悟和积累。


clock December 1, 2008 23:01 by author Sky Jia (贾超)

clock November 26, 2008 12:10 by author Sky Jia (贾超)

Do work to maximize the available communication bandwidth available to your team. Provide communications tools—like conference phone, Web cams, and hands free headsets—for your team and help them adapt their existing practices to distribution. 

Don’t continually reorganize your teams for each new project. Building teams takes time, building distributed teams takes even longer. Maximize your investments in team building by minimizing churn on teams. 

Do plan to travel, especially at the project’s pivotal points. Bring everyone together for the first couple of iterations, periodically during the project, and right before final release. 

Don’t distribute the work by system components, focus on user stories. Avoid organizing distributed teams by function—for example, the offshore test team. Both these approaches create knowledge silos within the team. 

Do provide tools to augment or replace those that only work within a team room—like a work item tracking system to replace sticky notes on whiteboards. 

Don’t let remote team members be forgotten in team meetings. Pair them up with a buddy and try putting everyone on the same footing by having all members call into conference calls at least occasionally. 

Do evolve the team’s practices as they identify better ways to deal with the challenges of geographic dispersion. Frequent retrospectives are the key to getting a team to consider how to improve.

Don’t forget to include everyone in frequent team retrospectives to identify what does and does not work for the team. 

Do focus on coaching. Make sure everyone understands why agile practices need to be adapted for distributed development.

 

Distributed Agile Development at Microsoft Patterns and Practices.pdf (1.06 mb)


clock November 24, 2008 17:58 by author Sky Jia (贾超)

作者 Dave Nicolette译者 郑柯 发布于 20081119下午356

很多人都觉得:迭代的长度应该由发布周期的长短确定。我不同意,我认为这两个周期之间不应有关系。相对于长迭代来说,短迭代可以提供更为频繁的客户反馈,同时也给予团队机会,让他们可以反思并改进自己的工作实践。短周期可以形成"心跳节奏",这样的快节奏也足以展现更多意义。由于短周期的本性使然,团队不大有机会创建过于冗长的工作项目,而这样的项目会使得人们很难产生成就感,除非等到大量的工作完成之后。即使发布的周期很长,下面这些好处仍然存在。

好处

  1. 快速响应。在不影响正在进行的工作的情况下优先快速响应变化。产品负责人、客户或是代理人在迭代中期改变优先级或是添加新功能,这样的情况很多见。如果迭代时间足够 短,这种状况就可以得到更好的处理,因为变更在下个迭代中就可以容纳进来了,这样也可以避免打乱当前迭代本不应受影响的正常节奏。
  2. 问题检测。成熟的敏捷团队能够发现流程上的问题并马上处理。然而,目前看来,很多敏捷团队仍然在学习曲线上前行,他们还没有成熟到可以自己 发现并解决问题的地步。他们需要根据项目度量数据的变化来识别问题。由于趋势要靠三个点的连线才能体现出来,而项目数据每个迭代才能收集一次,因此更短的 迭代可以更快地暴露问题。
  3. 范围管理。如果待办事项列表中的条目都很小,那就可以灵活移动。较长的迭代会产生较大的用户故事。如果产品负责人需要变更待办事项列表条目的优先级,如果用户故事较大,那么变更这些用户故事造成的影响也更大。较短的迭代则趋向产生较小的用户故事。遵循INVEST原则,产品负责人也更容易变更用户故事的优先级。
  4. 迭代规划和跟踪。长迭代产生的较大的用户故事,经常要被分解为"任务",也就是要将大块儿的开发工作拆分为可操作性更强的明细任务。接下 来,为了让团队知道所有用户故事的状态,这些任务要在迭代中跟踪,要么使用类似于"看板"的系统,要么使用迭代的燃尽图。很多团队每天都会停下来重新估算 尚未完成的个人任务。使用短迭代,可以去除所有这些内部流程的管理成本;用户故事变成了更小的工作单位,而人们也能够以更简单的方式跟踪迭代状态。
  5. 成为转向"无迭代流程"的基础。迭代式开发保留了一些瀑布开发过程固有的管理成本,即使我们付出代价想去掉它们也是如此。如果将每个迭代从 头到尾画一个价值流累积图(cumulative flow diagram),这些管理成本就会以"在途时间(lead time"的形式体现出来。我参与过的一些团队,他们在自己承受范围之内尽量压缩迭代的时间。我注意到他们可以消除大量类似的管理成本。迭代时间越短, 让一切工作顺利进行所需花费的流程管理成本就越少。

从另一方面来看,在有严格时间限制的迭代中工作,也可以带来一些敏捷方法的附加价值,包括频繁和有规律的演示和回顾、用来交付增量开发结果的一致性时间表、频繁得到客户反馈的机会、以及对于"心跳"或是"脉搏"类似节奏的感觉,这样的感觉可以让团队在长期的开发过程中保证认真投入。使用时间盒的方式工作是有一些额外的好处的,而有些团队在采纳无迭代的流程时会把这些好处丢掉,这就等于是"连孩子带洗澡水一起泼出去了"。而使用短迭代,可以减少转向超轻量级、无迭代的流程所带来的痛苦;这也是可以预期的。

人们在转向无迭代流程时经常会犯一个错误,他们会将所有与"迭代"有关系的实践都抛弃掉。我们要将"迭代"的概念与有附加价值的敏捷开发特定实践区分开,并寻找能够减少流程管理成本、同时还可以保留有价值实践的解决之道。

潜在问题

有人在使用短迭代时遇到了困难。短迭代的拥护者Mishkin Berteig也提到一些潜在的问题 

  • "密集的工作回让人筋疲力尽。"我想这是团队选择何种工作方式的问题。周期短,不一定意味着工作就一定密集。短迭代可能仅仅意味着小时间盒;也就是说,每 个时间盒承诺交付的工作更少了。在工作密度上不一定有什么变化。其他的敏捷原则(特别是"可持续的步调")就是为了防止发生筋疲力尽的情况。
  • "战略层面的思考很难跟日程相结合。"战略层面的思考跟每个迭代要做的具体工作没有太大干系。迭代是战术层面的。战略层面的思考是……呃,非战术层面的。这听起来更像是管理上的问题,而不是短迭代的特性之类的东西。
  • " 每个迭代必须完成的、耗费管理成本的相关任务占用了短迭代的大部分时间。"这似乎又是一个团队如何选择工作方式的问题。我曾观察到挤压迭代时间长度而引 发的一个有趣结果:人们首先"发现"一些并不是非常必要的管理任务,然后就不再做它们了。最后,团队只做必要的事情,换句话说,他们去除了流程中的浪费。 实际上,这些观察让我对Jim ShoreJava Ranch上的发言 保留意见。他认为更长的迭代给团队的压力更小,因此有经验的敏捷团队更适合用长期的迭代。我觉得我们不必在迭代规划上花费更多时间, 我认为迭代规划还可以更少些。我支持更短的迭代,如果客户可以采取拉式的方法以单件流 single piece flow)的方式提出需求,这些迭代甚至可能逐渐消弭。
  • "对团队之外的资源或是人员的等待,这会使得工作的完成要跨越多个迭代。"组织上的约束造成了此类状况。如果试图采取的迭代长 度过短,以至于组织不能应 对,这样做并不合适。如果真这么做了,也就不能称之为"迭代"了,因为不可能在那样短的时间内交付工作结果,而组织也无法吸收这样的结果。要想有所进步, 我们必须识别出组织的约束。我并不认为临时的组织约束(它们是临时的,只要你真心愿意改变)就会使得短迭代不可行。简单么?没人会这么想。但如果组织的变 革很容易的话,那就没什么乐趣了,不是么?

相关内容: Extremely Short Iterations as a Catalyst for Effective Prioritization of Work

作者简介

Dave Nicolette 1977年起就从事IT行业了,他在2002年找到了敏捷,并视其为传统IT行业很多内在问题的缓解和去除之道。从那时起,在敏捷和精益的思考和实践上,他就成为了一名尽心竭力的实践者和大力鼓吹的提倡者。他喜欢与IT从业人士分享经验和有益的实践,并积极参与到敏捷社区的活动中。Dave目前是美国 Valtech科技公司的敏捷团队教练。


clock November 24, 2008 17:53 by author Sky Jia (贾超)

作者 Mike Bria译者 郭晓刚 发布于 20081116上午244

表面上看,多数敏捷方法都简单地根据业务价值决定故事的开发顺序。但在很多情况下,更明智的做法是将增加业务价值与有意识的"获取知识"步骤结合起来。Alistair Cockburn介绍了如何有效地进行此种结合,以及如何借助这样的实践在正确的时间交付正确的功能。

Cockburn的阐述从一项基本断言入题——设计活动的关键产出是创造知识:

在任何团队的设计活动中,我们都是在解决一项当前仍未理解通透的问题,建立一种当前仍未理解通透的解决方案,用我们仍未完全领会的语言及技术来表达自身想法——而以上各方面都在我们的眼前不断变化着。 
随着工作进展,我们对问题了解得愈多,对技术了解得愈多,对规划中的方案了解得愈多……

接着Cockburn举出瀑布方法的典型特征——"大爆炸"式的集成作为极端的例子,说明它是如何妨碍任何实质上的知识获取,直到项目的最后阶段,从而必然导致没有时间应对的"大惊喜"。用精益的术语来说,积累起来的未经验证的设计决策,构成了不断增长的"库存(inventory"Cockburn的原话,"从减少风险的角度来说,我们认为该情形直到最后都留有很大风险,在很后的阶段才产生知识,总之不是什么赏心悦目之事。

Cockburn
接着介绍了一种敏捷的处理方式,在其中团队将早期的迭代重点放在"积累知识",也就是学习

团队及早地、经常地集成,可使"大惊喜"分散到许多小的阶段中。这样做,团队可及早发现自身的错误,"学习"到错在何处,并因而减少以后的集成出现重大失败的机会。换言之,"学习"因素对项目的影响越来越小。这是一件好事。

为了促进这种实践,Cockburn建议团队问自己"我们担心/害怕什么?"的问题,并且将开发前期的精力集中在减少那些恐惧因素,而不要盲从"业务价值高的优先"这种教条。他提醒说这一阶段的工作次序可能表现得没什么条理,"但是它会满足在花费同样金钱之下,知识提升速度从高到低的排列次序,和降低项目风险从多到少的次序

这种方法的底线是,一旦减轻了大的风险,就开始按照业务价值的次序安排工作

当知识曲线开始变平坦,那就是转向按照业务价值高低排列的时刻。这时候就与一般的敏捷建议相一致了。请注意,原则上在着力获取知识的阶段,业务价值也总是在提高的;因此并非把业务价值丢到一边,只不过获取业务价值不是主导的推动力。

读者还应该注意,Alistair特别明确警告不要将"获取知识""BDUF Big Design Up Front"的意义相混淆。

Cockburn在最后收尾时解释如何将这种实践与功能疏剪(Feature thinning的一种实际运用相结合,使项目有效地平滑收尾,最终有效地提升团队的敏捷程度:

当知识曲线与业务价值曲线都变平后,资方就处在一种位置,既可以按时交付一组疏剪过的功能(或因竞争对手的动作而提前!),又可以稍后交付完整的功能集合。决定权理所应当地在资方的手上。

一如既往,请把这篇新闻仅仅当作一则提纲挈领的广告,务必阅读Alistair的完整文章。文章中还包括了几幅很有说服力的图,Alistair也介绍了他在两个截然不同的实际项目中采用这种实践的经验。

那么,您的看法如何呢?Alistair的方法符合你的经验吗?假如把这种方法用在你过去的项目中会不会有帮助?现在的项目又如何,以后的呢?如果有帮助,好在哪里?如果没有,又为什么?你会不会觉得这种方法"不是敏捷"?请留下您的想法。

查看英文原文:Iterating To Acquire Knowledge, Not Just 'Business Value'


clock November 19, 2008 19:06 by author War3

原文出处:http://hi.baidu.com/interaction_design/blog/item/2f610b4e7c0fe0ccd1c86ae6.html 

这是一个著名的模型,把UCD过程中的每个工作步骤和内容都完整而流畅的概括进来。很大程度上帮助我理清了UCD相关的混乱头绪。以这个模型为基础,我整理了一个比较可行的UCD流程。

当然迫于条件的限制,我们不可能有机会去做用户研究相关的工作,通常是从竞争对手的分析中来获得关于用户的理解和灵感。用Jesse James Garrett的话说,在相同领域做相似的事情的研发团队,所服务的用户必定具有某种程度的相似性。按照产品分析和设计套路倒推,解剖优秀产品的设计策略,可能是快速建立用户认识的窍门。可能有人觉得理解用户是市场的事,显然这是片面的。其实理解用户能够在以用户为中心的设计过程中帮助设计决策,如果没有这个认识,很可能会在后面的设计决策和讨论中陷入个人英雄主义的表演和政治博弈之中。当然,寻找用户还能使我们收获更多的领域知识,整理对手的优缺点,并能在后续的概念设计、交互设计和原型设计中提供极大的参考价值。

这个流程不是一个快速开发的流程,虽然在用户分析中投机取巧节省了一点时间,但是在交互设计阶段需要消耗相当的努力和创造激情,当然还有时间和成本。在急于看到成果和关心"成本"的队伍中,很容易被一笔带过或敷衍了事,很多人习惯以看到界面设计框线图作为设计成果的标志,呵呵,画框线图其实是很简单的。缺少慎重的交互分析基础的框线图,很容易浮于形式而缺少内涵。

和朋友们交流一下吧!

六个阶段,每个阶段又有关键的工作内容和要求。

第一阶段:基础调研

竞争产品分析
寻找市场上的竞争产品,挑选3-5款进行解剖分析。整理竞争产品的功能规格;并分析规格代表的需求,需求背后的用户和用户目标;分析竞争产品的功能结构和交互设计,从产品设计的角度解释其优点、缺点及其原因,成为我们产品设计的第一手参考资料。

领域调研
结合上述分析基础和资料,纵观领域竞争格局、市场状况,利用网络论坛、关键字搜索等手段获得更多用户反馈、观点、前瞻性需求。

产出物:相应的对比分析文档和领域调研报告


第二阶段:产品分析

产品定位
从软件提供者的角度分析产品推出的意义和重点关注的方面,实际考量、丰满决策层的idea,明确列出产品定位,通过讨论修缮取得决策层的认可;

用户分析
结合竞争产品的分析资料,采用定性分析的方法,获得对产品目标用户在概念层面的认识;

产品概述
以软件提供的身份,以最简短的文字,向用户介绍产品,突出产品对用户的价值。避免功能点的简单罗列,而应该在归纳总结的基础上突出重点;

功能需求规格整理
在归纳关键功能的基础上,结合竞争产品规格整理的领域认识,从逻辑上梳理需求规格列表,重在逻辑关系清楚、组织和层级关系清晰。划定项目(设计和研发)范围;

产出物:用户分析文档和产品概述、功能规格列表


第三阶段:交互设计(功能结构和交互流程设计)

产品概念模型分析
从产品功能逻辑入手,结合对常见软件的经验积累和竞争产品的认识,加上对用户的理解,为产品设计一个尽量接近用户对产品运行方式理解的概念模型,成为产品设计的基础框架;

功能结构图
在产品概念模型的基础上丰富交互组件,并理顺交互组件之间的结构关系;

使用场景分析
模拟典型用户执行关键功能达到其目标的使用场景;

交互流程分析
模拟在上述概念模型和功能结构决定的产品框架之中,支持使用场景的关键操作过程(即鼠标点击步骤和屏幕引导路径);

产出物:产品设计文档的交互设计部分


第四阶段:原型设计(信息架构和界面原型设计)

信息架构和界面原型设计
设计产品界面中应该包含的控件数量和类型、控件之间的逻辑和组织关系,以支持用户对控件或控件组所代表的功能的理解,对用户操作的明确引导;所有界面设计成为一套完整的可模拟的产品原型;

设计要点说明
对界面设计的重点添加说明,帮助涉众对设计的理解;

产出物:产品设计文档的原型设计部分


第五阶段:详细设计(详细设计和交互逻辑表述)

详细设计
完善设计细节、交互文本和信息设计(Message box);

控件和交互逻辑表述
对界面控件/控件组/窗口的属性和行为进行标准化定义,梳理完整的交互逻辑,用状态迁移图或伪代码形式表示;

产出物:产品设计文档的详细设计部分


第六阶段:设计维护(研发跟踪和设计维护)

语言文档整理
设计通过评审之后,把产品中所有的交互文本整理成excel文档,预备研发工作;

研发跟踪维护
进入研发阶段后负责为研发工程师解释设计方案、问题修改、文档完善、Bug跟踪等;

产出物:产品语言文档,设计调整维护


Search

Calendar

<<  September 2010  >>
SuMoTuWeThFrSa
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

Categories

Tags