;

项目经理如何管理敏捷团队

发布时间: 作者:系统管理员 访问量:135

  采用敏捷方法的组织通常会对项目经理的作用及其日常工作产生影响。Scrum为项目经理转变为Scrum主管(Scrum mas ter)或是产品负责人(product owner)提供了可能。项目经理也能采用他们自己的工作方式与其他Scrum主管和敏捷团队一起工作。

  Jim Bird写的一篇博客文章《敏捷——项目经理需要做什么?》中讨论到了如何管理敏捷项目以及项目经理在敏捷团队中起到的作用。对Scrum中项目管理和项目经理的观点,他阐述如下:

  在Scrum(当今大部分人谈及敏捷方法时所指的那个Scrum)中,已经没有项目经理可以发挥的余地了:管理的职责已经分担给了产品负责人、Scrum主管和开发团队。

  项目经理可以选择成为Scrum主管(如果他们能接受公仆性质的领导角色然后学着成为一个高效的敏捷方法教练——当然,前提是团队接受了他们),或者成为产品负责人(如果他们拥有资深的领域知识或者其他技能),或者另谋高就。

  就像Jim描述的那样,一个组织可以决定将项目经理的角色转变为Scrum主管:

  虽然对于项目经理能否像Scrum主管那样高效工作颇具争议,但是从项目经理转变为团队的Scrum主管看起来似乎是最自然而然的事情。那些争议的焦点在于项目经理是否会接受职责和权利的改变,是否愿意改变他们与团队和组织中的其他成员的工作方式。

  Scrum主管是“流程负责人”和教练,而不是项目经理。他们帮助团队和产品负责人理解:如何在敏捷流程框架下工作,他们的角色和职责是什么,安排并主持会议和审查,指导团队成员以应对变更和冲突。

  他的博客文章描述了采用敏捷方法的组织必须面对的许多项目管理工作,而这些工作通常并非由敏捷团队来完成。以下这些示例包含了项目建立、对外交流和风险管理:

  首先,在项目启动——即第0次迭代(Iteration Zero)——之前有许多工作必须要做。确定股东。确立公司章程。项目预算及合同条款谈判。理解并组织官僚机构。解决公司管理、合规要求和各类约束等问题,这也是PMO(Project management office, 项目管理办公室)所需的。和HR、生产线经理和职能经理共事以促进团队合作。寻找并雇佣合适人选,给他们足够的空间和所需的工具。组织合作伙伴、供应商和合同商。合同签订、许可授权和其他法律事宜。

  很多人需要知道,在开发团队之外,项目当中正在发生什么——特别是在大的组织里的大的项目中。对外界,与团队之外、公司之外的人联系。对上级,与经理和负责人联系,让他们及时了解状况。虽然墙上的任务板、燃尽图和看板图对团队来说帮助很大,但对上级管理层、PMO和其他股东来说,他们往往需要的更多。他们需要清楚公司的整体发展状况,包括项目或者程序或者商务变更主动权。

  正确实践的Scrum(仔细吸收了极限编程工程实践)对范围风险、日程风险、需求规格风险和技术风险等普通软件开发风险是十分有效的。但那些来自团队之外的风险仍然需要管理:项目风险、政治风险、合作伙伴风险以及后勤风险、集成风险、数据质量风险、操作风险、安全风险、财务风险、法律风险、战略风险。

  根据Jim所述,组织机构仍然需要和敏捷团队共事的项目经理:

  虽然敏捷方法使得管理职责被分担到了整个团队当中,但这并不意味着就远离管理问题了。项目无法衡量,团队无法成功,除非让一个项目经理或者PMO或者拥有所需权利和能力的某个人来管理这些问题

  在《从项目经理到Scrum主管》中,Rohit Ratan Mani讨论了从瀑布方法到敏捷方法这一转变对项目经理的影响。他描述了当一个组织采用敏捷方法时会发生什么:

  理想场景下,一位懂敏捷方法的SM(Scrum主管)会以管理者的身份和团队共事从而驱动整个项目。但在现实当中,我们经常会遇到以下管理问题:

  项目计划在哪里?

  风险管理计划在哪里?

  关键路径是什么?

  任务完成了多少百分比

  项目的S-曲线在哪里?

  他建议项目经理应该承担Scrum主管的作用:

  在我看来,Scrum主管能够帮助他们理解新旧过程是如何对应起来的,从而起到填补缺口的作用。传统的项目经理工作知识,以及基于对Scrum主管角色的理解,这两方面都是承担起这个双重角色所必须的。一些争论的焦点在于Scrum主管对项目执行有着不同的作用和方法,而这并非传统项目经理所能取代的。在我看来,一个渴望采用敏捷方法的项目经理是能符合Scrum主管职责要求的,同时又能够填补Scrum团队和管理之间的空隙。

  据Vidya Venkat所说,Scrum主管和项目经理是可以共存的。她的文章《让项目经理适应Scrum》提供了以下2个Scrum主管和项目经理的日常工作列表:

  Scrum主管的作用

  管理Scrum过程 - 作为项目领导者的Scrum主管确保维持端到端的执行流程。

  确保团队动力和功能 – 工作的执行需要紧密的团队和良好定义的工作内容。这是Scrum主管需要管理的。

  消除障碍 – Scrum主管确保项目平稳运行并且清除遇到的障碍。

  制定sprint计划 – 任何一个项目都需要完成目标。Scrum主管的一个焦点就是制定计划、完善并且发布目标

  和外界保持联系 – 将消息传递下去是Scrum主管工作中相当重要的一方面。

  项目经理的作用

  管理项目的方方面面。项目经理是项目的领袖并且自始至终提供端到端的支持。

  制定目标。项目经理需要理解结果并确保它们是可测量的、现实的。

  鼓励“团队建设”。作为整个项目的主管,项目经理确保团队紧密协作并且人尽其用。

  确保项目沟通。项目领导者对全部信息沟通畅通负有唯一责任。

  (项目经理)是焦点。最后,项目经理是项目相关信息分享和沟通单一节点。因而它是一个重要的角色。

  在Agile Atlas上的《新任Scrum主管如何反败为胜》一文中,项目经理Elizabeth Lloyd写道有关她第一次担任Scrum主管的个人经验:项目管理者联盟

  担任Scrum主管和担任项目经理并不相同,许多次我不得不做出有意识的努力去对抗我的自然倾向。我不得不忘却已有的行为习惯同时去学习那些在项目管理中不曾用到的。

  Elizabeth分享了以下四点经验。她真希望当时在她成为Scrum主管之前能对这些能有所了解(因此,她将做的更好)。

  别总跟着你的直觉走(...)每当我内心浮现那个自作主张、身为项目经理的自己的时候,我学会了深呼吸然后暂停一下。取而代之的是,我让团队自己做决定,而我则扮演引导者的角色负责消除障碍而不是去控制讨论的结果。

  优先考虑价值,其次才是范围(...)我认识到我必须成为真正的Scrum主管:支持我的团队,精确地评估我们的开发速度,消除障碍,并规划出团队在由项目经理既定的日期前可以完成多少故事点(story points)。项目经理的职责是对项目范围提升关注,同时确保股东理解Scrum会对交付成果、时间线以及其他管理需要。

  定义,定义,再定义(...)在与几位Scrum主管同事进行了交流,并在回顾会议中鼓舞团队之后,我认识到团队并不清楚用户故事什么时候才算作准备好进入开发阶段了,他们对“准备好了”概念一无所知(…)。最终我们商定了9点,如果在sprint计划会议中有任意一点没有满足,团队成员都可以直接说“不”。

  坚守“Scrum枪”(意为坚持Scrum原则)当团队不想接更多工作的时候,我必须支持他们。那就意味着要和我们的产品负责人说“不”。在她(产品负责人)确信已计划周全并着手把事情安排得井井有条之前,我们对她晓之以Scrum理即可。



最新发布

    FreeMarker template error (DEBUG mode; use RETHROW in production!): For "#list" list source: Expected a sequence or collection, but this has evaluated to an extended_hash+string (com.jmis.contentmng.pojo.Content wrapped into f.e.b.StringModel): ==> [in template "jmis/pm/article/detail.html" at line 185, column 13] ---- FTL stack trace ("~" means nesting-related): - Failed at: #list content as chann [in template "jmis/pm/article/detail.html" at line 185, column 6] - Reached through: @cm_content_list count="5" titleLen="... [in template "jmis/pm/article/detail.html" at line 179, column 8] ---- Java stack trace (for programmers): ---- freemarker.core.NonSequenceOrCollectionException: [... Exception message was already printed; see it above ...] at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:285) at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:200) at freemarker.core.Environment.visitIteratorBlock(Environment.java:595) at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:81) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:67) at freemarker.core.Environment.visit(Environment.java:326) at freemarker.core.Environment.visit(Environment.java:368) at freemarker.core.Environment$NestedElementTemplateDirectiveBody.render(Environment.java:2727) at com.jmis.contentmng.action.directive.abs.TemplateDirectiveUtil.ProcessTemplate(TemplateDirectiveUtil.java:316) at com.jmis.contentmng.action.directive.ContentListDirective.execute(ContentListDirective.java:254) at freemarker.core.Environment.visit(Environment.java:426) at freemarker.core.UnifiedCall.accept(UnifiedCall.java:101) at freemarker.core.Environment.visit(Environment.java:326) at freemarker.core.Environment.visit(Environment.java:332) at freemarker.core.Environment.process(Environment.java:305) at freemarker.template.Template.process(Template.java:384) at com.jmis.contentmng.common.web.springmvc.SimpleFreeMarkerView.renderMergedTemplateModel(SimpleFreeMarkerView.java:153) at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:209) at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:244) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.frame.core.cache.PageEhCacheFilter.doFilter(PageEhCacheFilter.java:102) at net.sf.ehcache.constructs.web.filter.Filter.doFilter(Filter.java:86) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.frame.core.web.filter.XssFilter.doFilter(XssFilter.java:20) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)