为什么敏捷实践会遭遇失败?

作者 Geoffrey Wiseman译者 李剑

虽然众多敏捷专家都在帮助敏捷项目走向成功这方面投入了很多精力,但是我们也应当过一段时间就停下来思考一下,为什么有些敏捷项目或是对敏捷的实施会失败呢?了解了这些以后,或许我们就能在日后的实践过程中躲开前行路上的种种陷阱。

Jean Tabaka列出了导致敏捷实施失败的11点因素

敏捷方法已经遭到了种种质疑,因为有的时候它们并没有为采用它们的组织带来所预期的收益。但是在我担任敏捷教练的期间,我发现实际上敏捷实践并没有失败,而是由于种种因素导致了敏捷实施过程的失败。下面是我所列出的最重要的前十一种原因。看看有没有哪一条给你带来过同样的痛苦。

她所列出的11点因素如下所示:

  1. 没有真正有效地实施定期的回顾(retrospective)
  2. 没能让每个人都参加计划会议
  3. 没有注意实施敏捷所需的基本结构
  4. 为项目带来反面作用的ScrumMasters
  5. 要么是产品负责人(Product Owner)一直没有加入项目中,要么是项目中有太多的负责人,而他们的意见又不一致
  6. 因为遇到困难而放弃敏捷,回退到从前的开发流程
  7. 组织的执行高层只给予口头承诺
  8. 团队中缺少决策者和负责组织管理开发过程的人
  9. 远程团队中没有“布道者”,协助调整团队状态,保证敏捷实践的顺利实施
  10. 缺少支持自我学习提高的团队或是组织文化
  11. 讳疾忌医,宁愿逃避也不愿面对现实

以上种种,在你的敏捷软件开发中是否也碰到过一些(或是全部)呢?或者你还有什么可以添加到这个列表中来么?

Tom Hume描述了他们组织的一个名为《为什么敏捷会失败》的活动,他们总结出的一条结论就是:“如果敏捷没有起到作用,那么要么是你没有正确的实施,要么就是团队成员不是作敏捷的那块料”。《QA Strategies》列举了一些实施敏捷时遇到的挑战,从对细化管理的担心到过于热心的团队,这些都是实施敏捷的不利因素。Kevin Brady认为敏捷方法没有考虑到人类心理学的因素

  • 人们常常都会把自己的兴趣放到团队的兴趣之上。
  • 人们都更为关注自己的事情。
  • 商业产品的决策是基于理性的期望的。
  • Karl Popper的“协作活动第一定律”:你永远不可能找到超过五个人对任何事物的意见都会保持一致。

Eric D. Brown也认为这和人们自身有关,但是他是从另外一个角度来分析的:“这不在于使用的过程或是方法学……帮助项目成功取得成功的是参与项目开发的人。当然,过程在这方面也会起作用,但是如果没有比较好的团队成员,或者没有帮助这些人取得成功的组织,那么就算是再好的项目管理方法也会失败”。

您可以听一下对Jean Tabaka进行的采访播客以获得更多信息,或者你还可以在InfoQ敏捷社区中留言,告诉我们你认为导致实施敏捷失败的因素有哪些,而你又是怎样处理这些问题的。

查看英文原文:Why do Agile Adoptions Fail?

 

getline为什么失败?

11-06

#include rn#include rn#include rnusing namespace std;rnrnint main() rn rn // open for input and output and pre-position file poi nters to end of file rn fstream inOut("copyOut", fstream::ate | fstream::in | fstream::out); rn if (!inOut) rn cerr << "Unable to open file!" << endl; rn return EXIT_FAILURE; rn rn // inOut is opened in ate mode, so it starts out posit ioned at the end, rn // which we must remember as it is the original end-of-file position rn ifstream::pos_type end_mark = inOut.tellg(); rn inOut.seekg(0, fstream::beg); // reposition to start of the file rn int cnt = 0; // accumulator for byte count rn string line; // hold each line of input rn // while we haven't hit an error and are still reading the original data rn // and successfully read another line from the file rn while ((inOut.tellg() < end_mark) && getline(inOut,line)) rn rn cnt += line.size() + 1; // add 1 to account for the newline rn // remember current read marker rn ifstream::pos_type mark = inOut.tellg(); rn inOut.seekp(0, fstream::end);// set write marker to end rn inOut << cnt; // write the accumulated length rn // print separator if this is not the last line rn if (mark != end_mark) inOut << " "; rn inOut.flush();rn inOut.seekg(mark); // restore read position rn rn inOut.clear(); // clear flags in case we hit an error rn inOut.seekp(0, fstream::end); // seek to end rn inOut << "\n"; // write a newline at end of file rn return 0; rn rnrncopyOut文件有若干行,没有以空行结束的话最后一个getline会失败,这是为什么?rnrn例如对于包含如下三行内容的文件(最后面没有换行符):rn1rn1rn1rn执行程序后文件内容应该是rn1rn1rn12 4 9rn才对啊,为什么读最后一行getline会失败?导致输出变成了rn1rn1rn12 4 rn

为什么会绘图失败

12-15

某个教科书上的截屏程序如下:rn //复制桌面, 编程3/4大小rn HWND h = ::GetDesktopWindow();rn RECT rect;rn ::GetWindowRect(h, &rect); rn CDC dc;rn dc.CreateDC("DISPLAY", NULL, NULL, NULL);rn CBitmap bm;rn int Width = (rect.right - rect.left);rn int Height = (rect.bottom - rect.top);rn bm.CreateCompatibleBitmap(&dc, Width * 3 / 4, Height * 3 / 4);rn CDC tdc;rn tdc.CreateCompatibleDC(&dc);rn CBitmap *pOld = dc.SelectObject(&bm);rn tdc.StretchBlt(0, 0, Width * 3 / 4, Height * 3 / 4, &dc, 0, 0, Width, Height, SRCCOPY);rn tdc.SelectObject(pOld);rn BITMAP btm;rn bm.GetBitmap(&btm);rn DWORD size = btm.bmWidth * btm.bmHeight;rn BYTE *lpData = (BYTE *)GlobalAlloc(GPTR, size);rn //构造BMP图的头rn BITMAPINFOHEADER bih;rn bih.biBitCount = btm.bmBitsPixel;rn bih.biClrImportant = 0;rn bih.biClrUsed = 0;rn bih.biCompression = 0;rn bih.biHeight = btm.bmHeight;rn bih.biPlanes = 1;rn bih.biSize = sizeof(BITMAPINFOHEADER);rn bih.biSizeImage = size;rn bih.biWidth = btm.bmWidth;rn bih.biXPelsPerMeter = 0;rn bih.biYPelsPerMeter = 0;rn GetDIBits(dc, bm, 0, bih.biHeight, lpData, (BITMAPINFO*)&bih, DIB_RGB_COLORS);rn //保存到系统临时文件下rn char name[256];rn GetTempPath(256, name);//取临时文件夹rn strcat(name, "\pict_0.bmp");rn BITMAPFILEHEADER bfh;rn bfh.bfReserved1 = bfh.bfReserved2 = 0;rn bfh.bfType = 0x4d42;rn bfh.bfSize = 54 + size;rn bfh.bfOffBits = 54;rn CFile bf;rn if(bf.Open(name, CFile::modeCreate|CFile::modeWrite))rn rn bf.WriteHuge(&bfh, sizeof(BITMAPFILEHEADER));rn bf.WriteHuge(&bih, sizeof(BITMAPINFOHEADER));rn bf.WriteHuge(lpData, size);rn bf.Close();rn rn GlobalFree(lpData);rn执行完毕后,找到所创建的pict_0.bmp, 打开后,却出现了“绘图失败”,为什么?改程序错在哪里呢?请高手指点!!

为什么RegisterClass会失败

02-17

各位大佬好!请教如下问题。我的程序要Skype通讯,利用Skype发的SDK中的例子做了小许改动,在win2000和winxp上都没问问题,可程序在win98上却失败了。如下:rnvoid main(void)rn rn // create window classrn // create dummy/hidden window for processing messagesrn // run message loop threadrn // do application control until exitrn // exit: send QUIT message to our own windowrn // wait until thred terminatesrn // destroy main windowrn // destroy window classrn uiGlobal_MsgID_SkypeControlAPIAttach=RegisterWindowMessage("SkypeControlAPIAttach");rn uiGlobal_MsgID_SkypeControlAPIDiscover=RegisterWindowMessage("SkypeControlAPIDiscover");rn if( uiGlobal_MsgID_SkypeControlAPIAttach!=0 && uiGlobal_MsgID_SkypeControlAPIDiscover!=0 )rn rn printf("STEP 1\n");rn if( Initialize_CreateWindowClass() )rn rn printf("STEP 2\n");rn if( Initialize_CreateMainWindow() )rn rn printf("STEP 3\n");rn hGlobal_ThreadShutdownEvent=CreateEvent( NULL, TRUE, FALSE, NULL);rn if( hGlobal_ThreadShutdownEvent!=NULL )rn rn printf("STEP 4\n");rn if( _beginthread( &Global_InputProcessingThread, 64*1024, NULL)!=(unsigned long)-1 )rn rn printf("STEP 5\n");rn Global_MessageLoop();rn Global_Console_CancelReadRow();rn WaitForSingleObject( hGlobal_ThreadShutdownEvent, INFINITE);rn rn CloseHandle(hGlobal_ThreadShutdownEvent);rn rn DeInitialize_DestroyMainWindow();rn rn DeInitialize_DestroyWindowClass();rn rn rn rn在第一步中bool Initialize_CreateWindowClass(void)rn rn unsigned char *paucUUIDString;rn RPC_STATUS lUUIDResult;rn bool fReturnStatus;rn UUID oUUID;rnrn fReturnStatus=false;rn lUUIDResult=UuidCreate(&oUUID);rn hInit_ProcessHandle=(HINSTANCE)OpenProcess( PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());rn if( hInit_ProcessHandle!=NULL && (lUUIDResult==RPC_S_OK || lUUIDResult==RPC_S_UUID_LOCAL_ONLY) )rn rnPrintf("open process ok\n");rn if( UuidToString( &oUUID, &paucUUIDString)==RPC_S_OK )rn rnPrintf("uuid converse ok\n");rn WNDCLASS oWindowClass;rnrn strcpy( acInit_WindowClassName, "Skype-API-Test-");rn strcat( acInit_WindowClassName, (char *)paucUUIDString);rnrn oWindowClass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;rn oWindowClass.lpfnWndProc=(WNDPROC)&SkypeAPITest_Windows_WindowProc;rn oWindowClass.cbClsExtra=0;rn oWindowClass.cbWndExtra=0;rn oWindowClass.hInstance=hInit_ProcessHandle;rn oWindowClass.hIcon=NULL;rn oWindowClass.hCursor=NULL;rn oWindowClass.hbrBackground=NULL;rn oWindowClass.lpszMenuName=NULL;rn oWindowClass.lpszClassName=acInit_WindowClassName;rnrn if( RegisterClass(&oWindowClass)!=0 )rn rn fReturnStatus=true;rn rn elsern rn printf("register wndclass failure!!!\n");rn rnrn rnrn RpcStringFree(&paucUUIDString);rn rn rn if( fReturnStatus==false )rn CloseHandle(hInit_ProcessHandle),hInit_ProcessHandle=NULL;rn return(fReturnStatus);rn rn在win98上运行时输出:rnstep 1rnopen process okrnuuid converse okrnregister wndClass failurern我把上面oWindowClass.hInstance=hInit_ProcessHandle;改为rnoWindowClass.hInstance=NULL;后再输出就是:rnstep 1rnopen process okrnuuid converse okrnstep 2rn上面那个线程是要处理输入输出的,所以不能没有,win98也是支持多线程的,我的程序为什么就跑不起来呢?请给点指。

为什么失败??

02-11

<%@ page contentType="text/html;charset=gb2312"%> rn<%@ page import="java.sql.*"%> rnrnrn<%Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); rnString url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs"; rnString user="sa"; rnString password=""; rnConnection conn= DriverManager.getConnection(url,user,password); rnStatement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); rnString sql="select * from test"; rnResultSet rs=stmt.executeQuery(sql); rnwhile(rs.next()) %> rnrn您的第一个字段内容为:<%=rs.getString(1)%> rnrn您的第二个字段内容为:<%=rs.getString(2)%> rnrn<%%> rnrn<%out.print("hello");%> rnrn<%rs.close(); rnrnstmt.close(); rnrnconn.close(); rnrn%> rnrn rnrnrnrnrntype Exception reportrnrnmessage rnrndescription The server encountered an internal error () that prevented it from fulfilling this request.rnrnexception rnrnorg.apache.jasper.JasperException: com.microsoft.jdbc.sqlserver.SQLServerDriverrn at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:254)rn at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)rn at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)rn at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)rn at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)rn at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2417)rn at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)rn at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:193)rn at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:781)rn at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:549)rn at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:589)rn at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:666)rn at java.lang.Thread.run(Unknown Source)rnrnrnroot cause rnrnjavax.servlet.ServletException: com.microsoft.jdbc.sqlserver.SQLServerDriverrn at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:536)rn at org.apache.jsp.date_jsp._jspService(date_jsp.java:78)rn at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:137)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)rn at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:210)rn at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)rn at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)rn at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)rn at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)rn at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2417)rn at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)rn at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)rn at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)rn at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)rn at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)rn at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:193)rn at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:781)rn at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:549)rn at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:589)rn at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:666)rn at java.lang.Thread.run(Unknown Source)rnrn

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试