@font-face { font-family: octicons-anchor; src: url(“https://cdnjs.cloudflare.com/ajax/libs/octicons/4.4.0/font/octicons.woff”) format(“woff”) }
* { box-sizing: border-box }
body .markdown-body { padding: 45px; border: 1px solid rgba(221, 221, 221, 1); border-radius: 3px; word-wrap: break-word }
pre { font: 12px Consolas, “Liberation Mono”, Menlo, Courier, monospace }
.markdown-body { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; color: rgba(51, 51, 51, 1); font-family: “Helvetica Neue”, Helvetica, “Segoe UI”, Arial, freesans, sans-serif, “Apple Color Emoji”, “Segoe UI Emoji”, “Segoe UI Symbol”; font-size: 16px; line-height: 1.6; word-wrap: break-word }
.markdown-body a { background-color: rgba(0, 0, 0, 0) }
.markdown-body a:active, .markdown-body a:hover { outline: 0 }
.markdown-body strong { font-weight: bold }
.markdown-body h1 { font-size: 2em; margin: 0.67em 0 }
.markdown-body img { border: 0 }
.markdown-body hr { box-sizing: content-box; height: 0 }
.markdown-body pre { overflow: auto }
.markdown-body code, .markdown-body kbd, .markdown-body pre { font-family: monospace, monospace; font-size: 1em }
.markdown-body input { color: inherit; margin: 0 }
.markdown-body html input[disabled] { cursor: default }
.markdown-body input { line-height: normal }
.markdown-body input[type=”checkbox”] { box-sizing: border-box; padding: 0 }
.markdown-body table { border-collapse: collapse; border-spacing: 0 }
.markdown-body td, .markdown-body th { padding: 0 }
.markdown-body input { font: 13px / 1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, “Apple Color Emoji”, “Segoe UI Emoji”, “Segoe UI Symbol” }
.markdown-body a { color: rgba(64, 120, 192, 1); text-decoration: none }
.markdown-body a:hover, .markdown-body a:active { text-decoration: underline }
.markdown-body hr { height: 0; margin: 15px 0; overflow: hidden; background: rgba(0, 0, 0, 0); border-top: 0; border-right: 0; border-bottom: 1px solid rgba(221, 221, 221, 1); border-left: 0 }
.markdown-body hr:before { display: table; content: “” }
.markdown-body hr:after { display: table; clear: both; content: “” }
.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { margin-top: 15px; margin-bottom: 15px; line-height: 1.1 }
.markdown-body h1 { font-size: 30px }
.markdown-body h2 { font-size: 21px }
.markdown-body h3 { font-size: 16px }
.markdown-body h4 { font-size: 14px }
.markdown-body h5 { font-size: 12px }
.markdown-body h6 { font-size: 11px }
.markdown-body blockquote { margin: 0 }
.markdown-body ul, .markdown-body ol { padding: 0; margin-top: 0; margin-bottom: 0 }
.markdown-body ol ol, .markdown-body ul ol { list-style-type: lower-roman }
.markdown-body ul ul ol, .markdown-body ul ol ol, .markdown-body ol ul ol, .markdown-body ol ol ol { list-style-type: lower-alpha }
.markdown-body dd { margin-left: 0 }
.markdown-body code { font-family: Consolas, “Liberation Mono”, Menlo, Courier, monospace; font-size: 12px }
.markdown-body pre { margin-top: 0; margin-bottom: 0; font: 12px Consolas, “Liberation Mono”, Menlo, Courier, monospace }
{ opacity: 0 }
.markdown-body .octicon { font: normal normal normal 16px / 1 octicons-anchor; display: inline-block; text-decoration: none; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none }
.markdown-body .octicon-link:before { content: “” }
.markdown-body:before { display: table; content: “” }
.markdown-body:after { display: table; clear: both; content: “” }
.markdown-body>*:first-child { margin-top: 0 !important }
.markdown-body>*:last-child { margin-bottom: 0 !important }
.markdown-body a:not([href]) { color: inherit; text-decoration: none }
.markdown-body .anchor { display: inline-block; padding-right: 2px; margin-left: -18px }
.markdown-body .anchor:focus { outline: none }
.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { margin-top: 1em; margin-bottom: 16px; font-weight: bold; line-height: 1.4 }
.markdown-body h1 .octicon-link, .markdown-body h2 .octicon-link, .markdown-body h3 .octicon-link, .markdown-body h4 .octicon-link, .markdown-body h5 .octicon-link, .markdown-body h6 .octicon-link { color: rgba(0, 0, 0, 1); vertical-align: middle; visibility: hidden }
.markdown-body h1:hover .anchor, .markdown-body h2:hover .anchor, .markdown-body h3:hover .anchor, .markdown-body h4:hover .anchor, .markdown-body h5:hover .anchor, .markdown-body h6:hover .anchor { text-decoration: none }
.markdown-body h1:hover .anchor .octicon-link, .markdown-body h2:hover .anchor .octicon-link, .markdown-body h3:hover .anchor .octicon-link, .markdown-body h4:hover .anchor .octicon-link, .markdown-body h5:hover .anchor .octicon-link, .markdown-body h6:hover .anchor .octicon-link { visibility: visible }
.markdown-body h1 { padding-bottom: 0.3em; font-size: 2.25em; line-height: 1.2; border-bottom: 1px solid rgba(238, 238, 238, 1) }
.markdown-body h1 .anchor { line-height: 1 }
.markdown-body h2 { padding-bottom: 0.3em; font-size: 1.75em; line-height: 1.225; border-bottom: 1px solid rgba(238, 238, 238, 1) }
.markdown-body h2 .anchor { line-height: 1 }
.markdown-body h3 { font-size: 1.5em; line-height: 1.43 }
.markdown-body h3 .anchor { line-height: 1.2 }
.markdown-body h4 { font-size: 1.25em }
.markdown-body h4 .anchor { line-height: 1.2 }
.markdown-body h5 { font-size: 1em }
.markdown-body h5 .anchor { line-height: 1.1 }
.markdown-body h6 { font-size: 1em; color: rgba(119, 119, 119, 1) }
.markdown-body h6 .anchor { line-height: 1.1 }
.markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre { margin-top: 0; margin-bottom: 16px }
.markdown-body hr { height: 4px; padding: 0; margin: 16px 0; background-color: rgba(231, 231, 231, 1); border: 0 none }
.markdown-body ul, .markdown-body ol { padding-left: 2em }
.markdown-body ul ul, .markdown-body ul ol, .markdown-body ol ol, .markdown-body ol ul { margin-top: 0; margin-bottom: 0 }
.markdown-body li>p { margin-top: 16px }
.markdown-body dl { padding: 0 }
.markdown-body dl dt { padding: 0; margin-top: 16px; font-size: 1em; font-style: italic; font-weight: bold }
.markdown-body dl dd { padding: 0 16px; margin-bottom: 16px }
.markdown-body blockquote { padding: 0 15px; color: rgba(119, 119, 119, 1); border-left: 4px solid rgba(221, 221, 221, 1) }
.markdown-body blockquote>:first-child { margin-top: 0 }
.markdown-body blockquote>:last-child { margin-bottom: 0 }
.markdown-body table { display: block; width: 100%; overflow: auto; word-break: keep-all }
.markdown-body table th { font-weight: bold }
.markdown-body table th, .markdown-body table td { padding: 6px 13px; border: 1px solid rgba(221, 221, 221, 1) }
.markdown-body table tr { background-color: rgba(255, 255, 255, 1); border-top: 1px solid rgba(204, 204, 204, 1) }
.markdown-body table tr:nth-child(2n) { background-color: rgba(248, 248, 248, 1) }
.markdown-body img { max-width: 100%; box-sizing: content-box; background-color: rgba(255, 255, 255, 1) }
.markdown-body code { padding: 0.2em 0; margin: 0; font-size: 85%; background-color: rgba(0, 0, 0, 0.04); border-radius: 3px }
.markdown-body code:before, .markdown-body code:after { letter-spacing: -0.2em; content: ” ” }
.markdown-body pre>code { padding: 0; margin: 0; font-size: 100%; word-break: normal; white-space: pre; background: rgba(0, 0, 0, 0); border: 0 }
.markdown-body .highlight { margin-bottom: 16px }
.markdown-body .highlight pre, .markdown-body pre { padding: 16px; overflow: auto; font-size: 85%; line-height: 1.45; background-color: rgba(247, 247, 247, 1); border-radius: 3px }
.markdown-body .highlight pre { margin-bottom: 0; word-break: normal }
.markdown-body pre { word-wrap: normal }
.markdown-body pre code { display: inline; max-width: initial; padding: 0; margin: 0; overflow: initial; line-height: inherit; word-wrap: normal; background-color: rgba(0, 0, 0, 0); border: 0 }
.markdown-body pre code:before, .markdown-body pre code:after { content: normal }
.markdown-body kbd { display: inline-block; padding: 3px 5px; font-size: 11px; line-height: 10px; color: rgba(85, 85, 85, 1); vertical-align: middle; background-color: rgba(252, 252, 252, 1); border-top: 1px solid rgba(204, 204, 204, 1); border-right: 1px solid rgba(204, 204, 204, 1); border-bottom: 1px solid rgba(187, 187, 187, 1); border-left: 1px solid rgba(204, 204, 204, 1); border-radius: 3px; box-shadow: inset 0 -1px rgba(187, 187, 187, 1) }
.markdown-body .pl-c { color: rgba(150, 152, 150, 1) }
.markdown-body .pl-c1, .markdown-body .pl-s .pl-v { color: rgba(0, 134, 179, 1) }
.markdown-body .pl-e, .markdown-body .pl-en { color: rgba(121, 93, 163, 1) }
.markdown-body .pl-s .pl-s1, .markdown-body .pl-smi { color: rgba(51, 51, 51, 1) }
.markdown-body .pl-ent { color: rgba(99, 163, 92, 1) }
.markdown-body .pl-k { color: rgba(167, 29, 93, 1) }
.markdown-body .pl-pds, .markdown-body .pl-s, .markdown-body .pl-s .pl-pse .pl-s1, .markdown-body .pl-sr, .markdown-body .pl-sr .pl-cce, .markdown-body .pl-sr .pl-sra, .markdown-body .pl-sr .pl-sre { color: rgba(24, 54, 145, 1) }
.markdown-body .pl-v { color: rgba(237, 106, 67, 1) }
.markdown-body .pl-id { color: rgba(181, 42, 29, 1) }
.markdown-body .pl-ii { background-color: rgba(181, 42, 29, 1); color: rgba(248, 248, 248, 1) }
.markdown-body .pl-sr .pl-cce { color: rgba(99, 163, 92, 1); font-weight: bold }
.markdown-body .pl-ml { color: rgba(105, 58, 23, 1) }
.markdown-body .pl-mh, .markdown-body .pl-mh .pl-en, .markdown-body .pl-ms { color: rgba(29, 62, 129, 1); font-weight: bold }
.markdown-body .pl-mq { color: rgba(0, 128, 128, 1) }
.markdown-body .pl-mi { color: rgba(51, 51, 51, 1); font-style: italic }
.markdown-body .pl-mb { color: rgba(51, 51, 51, 1); font-weight: bold }
.markdown-body .pl-md { background-color: rgba(255, 236, 236, 1); color: rgba(189, 44, 0, 1) }
.markdown-body .pl-mi1 { background-color: rgba(234, 255, 234, 1); color: rgba(85, 165, 50, 1) }
.markdown-body .pl-mdr { color: rgba(121, 93, 163, 1); font-weight: bold }
.markdown-body .pl-mo { color: rgba(29, 62, 129, 1) }
.markdown-body kbd { display: inline-block; padding: 3px 5px; font: 11px / 10px Consolas, “Liberation Mono”, Menlo, Courier, monospace; color: rgba(85, 85, 85, 1); vertical-align: middle; background-color: rgba(252, 252, 252, 1); border-top: 1px solid rgba(204, 204, 204, 1); border-right: 1px solid rgba(204, 204, 204, 1); border-bottom: 1px solid rgba(187, 187, 187, 1); border-left: 1px solid rgba(204, 204, 204, 1); border-radius: 3px; box-shadow: inset 0 -1px rgba(187, 187, 187, 1) }
.markdown-body .plan-price-unit { color: rgba(118, 118, 118, 1); font-weight: normal }
.markdown-body .task-list-item { list-style-type: none }
.markdown-body .task-list-item+.task-list-item { margin-top: 3px }
.markdown-body .task-list-item input { margin: 0 0.35em 0.25em -1.6em; vertical-align: middle }
.markdown-body .plan-choice { padding: 15px 15px 15px 40px; display: block; border: 1px solid rgba(224, 224, 224, 1); position: relative; font-weight: normal; background-color: rgba(250, 250, 250, 1) }
.markdown-body .plan-choice.open { background-color: rgba(255, 255, 255, 1) }
.markdown-body .plan-choice.open .plan-choice-seat-breakdown { display: block }
.markdown-body .plan-choice-free { border-radius: 3px 3px 0 0 }
.markdown-body .plan-choice-paid { border-radius: 0 0 3px 3px; border-top: 0; margin-bottom: 20px }
.markdown-body .plan-choice-radio { position: absolute; left: 15px; top: 18px }
.markdown-body .plan-choice-exp { color: rgba(153, 153, 153, 1); font-size: 12px; margin-top: 5px }
.markdown-body .plan-choice-seat-breakdown { margin-top: 10px; display: none }
.markdown-body :checked+.radio-label { z-index: 1; position: relative; border-color: rgba(64, 120, 192, 1) }
@media print { body .markdown-body { padding: 0; border: none } }

 

 

项目背景

客户已有运行多年的官网老站(PC端),想在今年对老站进行一次UI全面更新、功能全部平移的升级,对接新的运营后端,然后建立官网小程序端且与官网PC端进行联动,使得品牌自有渠道能够更加全面化。

 

挑战

  • 时间紧。五月份进行Inception Workshop,确定项目交付范围与架构方案。官网六月初开始开发,小程序八月份开始开发,整个项目九月中旬必须上线。
  • 系统集成和数据迁移。系统需要对接客户的CRM,对接3个服务商,需要对老官网历史数据(订单、会员等)进行迁移。
  • 多团队沟通。小程序设计稿由第三方提供,因此多出了沟通、确认的时间,以及把控第三方交付的时间,以避免交付进度的影响。

 

迭代计划

Inception Workshop一结束,差不多就开始整理整个项目涉及的故事和技术卡,按照两周一迭代进行迭代计划安排并与客户确认,每个迭代第一周周三安排跟客户showcase上一周的预定的交付结果,得到反馈并安排进行改进。官网项目比较顺利,改造自定义了一下SSR框架就能开始进行开发,并且因为历史原因,还能享受到上一个项目遗留的一些福利,当然也少不了一些坑。

小程序的时间比较紧,相当于整个复制了一遍官网的功能,主要是前端任务,后端可以复用官网后端,因此一开始就给团队同学同步到整个项目的情况,让大家有一个大概的心理准备。然后就是与官网类似的处理,整个交付内容进行迭代排期并与客户确认,前期尽量能多做一些,避免后期怎么努力都无法完成的囧镜。

 

项目进行时

整个项目的过程中,PM会根据迭代完成情况灵活的找外援加入项目进行支援,以免交付延期。每日的站会(Standup Meeting)更新,让团队能对当前进度有一个大概的了解以及同步一些突发信息。定期的回顾会议(Retrospective Meeting)能暴露团队内部问题,将风险扼杀于苗头,鼓励能为团队带来正向帮助的行为,及时停止不好的做法。

迭代会议(IPM)能让团队对下一个迭代具体要做的事情有一个详细的了解,进行大致的估点,以便check开发进度情况。技术人员定期的CodeReview成为一个大家交流的时段,发现风险,指出问题,互相提高,还可以帮助新人快速的融入团队。

根据团队内部人员情况,可以定期进行一对一沟通,了解个人诉求或是给与近况反馈都是一个不错的渠道。TL应考虑团队内部人员提升自己的诉求,在一些安排上给与倾斜和鼓励,发现问题也需要提前制止。

 

不足之处

  • 后期对卡墙(Jira)的管理松懈。导致有些问题反复修改,且丢失context
  • 项目对运营后台有一些的定制化配置,没有提前准备运营需要了解的后台操作资料和培训,导致后期花费大量精力帮助运营进行后台配置与更新
  • 人员(QA)变动频繁。公司处于高速发展阶段,项目经历了4个QA,因此有些context可能丢失,测试不到位,导致项目上线出了一些低级问题。比如上线后发现部分浏览器有支付兼容问题
  • 甲乙方定位太角色化,不能站在专业角度评估客户需求(项目做完感觉都一样,客户是爸爸)
  • 与第三方合作交付产物管控不到位,导致第三方设计稿的延迟影响到我们的交付计划
  • 与客户沟通的需求,后面有一些没有进行邮件确认,导致交付验收阶段因一些需求上的问题产生不愉快(这个完全没必要的)
  • 对第三方系统的了解不充分和集成系统的需求整理不清晰导致后续一系列的开发、测试都不到位,以致上线出了不可控的问题

 

项目总结

  • 提前评估项目的风险点,且在项目进行过程中持续维护,后期安排足够的时间进行调研与分析
  • 与第三方合作一定要有自己的规划,并且将定好的规划提前与第三方确认时间,然后派人提前专门细致的了解第三方需求详细点,确定好具体的业务场景,再来规划己方与第三方的具体集成的点。此外,在进行的过程中,还应注意定时检查合作进度,管控风险
  • 与客户沟通的所有需求都要进行邮件的二次确认,一个是能够对所有需求来源有所记录,另一个是能避免后面的不必要的消耗
  • 开发管理不能松懈,尽量做到所有的改动都能有卡,能够进行追溯
  • 对后期交付时所需要的资料提前准备,对需要进行培训的人员提前约好时间进行沟通培训

在前端这块的管理上,做的还不够。前期经常codereview,然后效果都还不错,让我有了一些错觉就是当前团队趋于稳定,中后期即便是加班比较多,大家气氛这块我觉得都还好。不过在项目后期的时候,有些疏于管理,然后大家有些人也被分配到了其他项目,和同事们的交流不够,没有及时的顾及到一些个人情绪,这块是可以加强的。

作为一个Lead,不论同事是否还在一个项目都应该及时的去了解近况,给与自己力所能及的帮助,这样才能产生向心力,以帮助一些比较迷茫的同学找到方向,看见灯塔。

整个项目时间不长,得失还是挺多的,不论是管理还是技术上,都会有一些心得。然后项目的ROI还不错,得到公司领导的肯定,最后客户那边的反馈也还不错,算是对大家努力的一种认可。

ps: 及时总结,静心沉淀;如风少年,砥砺前行。

如想了解更多,请移步我的博客

欢迎关注我的公众号 “和F君一起xx”

版权声明:本文为wfsovereign原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wfsovereign/p/11913211.html