zoukankan      html  css  js  c++  java
  • 产品管理之敏捷之路(一)——携手同行,走自己的敏捷之路

    这是我最近在公司内部培训所整理的资料,本篇原本是PPT,我在这里整理成博客分享给大家。

    另外,最近因事回家待了一个月,所以很多东西都耽搁了,包括Magicodes.NET,这个直到现在我都没有时间去更新它,希望下周开始能够逐步投入少量时间。

    本篇作为开篇,在此,我先列下本系列的内容(可能有些篇章过多,会进行拆分),希望和大家探讨交流:

    1. 产品管理之敏捷之路(一)——携手同行,走自己的敏捷之路
    2. 产品管理之敏捷之路(二)——使用TFS生成服务+PowerShell实现持续集成
    3. 产品管理之敏捷之路(三)——使用Worktile+Sharepoint进行规范梳理
    4. 产品管理之敏捷之路(四)——使用LessChat进行渠道整合(反馈、开发、日志、通知)
    5. 产品管理之敏捷之路(五)——使用Worktile进行产品管理

    现在开始说说本章的主题(根据我之前培训的PPT改编而成)

    携手同行,走自己的敏捷之路

    前言

    近来,我一直在思考:

    • 如何在有限的资源下,开发出更可用的产品?
    • 如何更有效的开发与合作,以及提升团队的开发效率?
    • 如何调动团队中每一个人的积极性,让每一个人都能够在产品的迭代中不断成长?
    • 如何使产品团队内部协作更合理更规范,责任更明确?

    因此,在本篇的内容中,希望更多的是引导而不是灌输。在此开始之前,我想表达下个人观点:

    • 我从未对一种开发模式寄予全部希望。期望它能解决我们现在固有的所有问题是不现实的,它可能是甜蜜剂,当然也有可能是催化剂!
      真正让我寄予希望的是团队中的每一个人,也就是我们在座的每一个人。
    • 世界一直在变,而唯一不变的是变化。我们一路走来,从项目团队到产品团队,从互不相识到协同工作,我们需要变化,我们需要调整,我们需要成长,以组成一个更高效更合理的产品团队——我们是一个整体,我们需要携手并进,精诚合作。
    • 敏捷管理不可复制,因此我们需要走出自己的敏捷之路。

    书籍是人类进步的阶梯

    在此之前先推荐两本书,不是我自己的。

    淘宝技术这十年

    这不是一本好的技术书,但是却绝对值得做产品的人看。

    引用书里的一句话:“任何网站的发展都不是一蹴而就的,通常是在什么阶段采用什么技术。在发展的过程中,网站会遇到各种各样的问题,正是这些原因才推动着技术的进步与发展,而技术的发展反过来又会促进业务的更大提升。两者互为因果,相互促进”。

    因此,任何一个产品,都有一个从烂到好的过程,产品的完善是一步一个脚印踏踏实实做出来的,是一点一点进步起来的。从书中我们可以看到淘宝其实并没有想象中的那么神话,他们早期的产品也是伴随着各种BUG,各种不稳定,各种不完善,这跟我们目前开发的产品一样,所以我们无需妄自菲薄。但是,我们需要有坚持做好产品的决心与毅力,一点一点的完善,一点一点的改进,最终我们也一样能开发出好的产品。

    右下角为淘宝早期风格。

    imageimage

    精益创业

    当决定做一个东西的时候,不要一开始就把目标定的很宏大很完善,一开始就要设计一个能容纳多少访问量的架构,其实计划永远赶不上变化,你的系统总是随着用户的扩大而渐进改进的。与其一开始就花费巨大的精力与时间去想以后用户规模到多大之后我们的系统还能不能用的问题,还不如好好满足当前用户的需求,至于以后,那自有以后的应对策略。否则当你花费巨大的精力想要打造一个容纳千万访问量的系统,最后却发现你的系统连十万访问量都达不到。这也是敏捷开发管理的核心理念(亦是精益创业的核心思想),即先在市场中投入一个极简的原型产品,然后通过不断的学习和有价值的用户反馈(经过证实的认知) ,对产品进行快速迭代优化,以期适应市场。

    image

    微软Visual Studio团队的敏捷之路

    在讨论敏捷之前,我们先来看看Visual Studio团队的敏捷之路。

    •Visual Studio是微软最重要的核心开发工具,到去年10月止,全球.NET开发人员近6百万人,光是VS 2013年版本,下载次数就达到7百万次。

    •参与VS开发的人数超过4,700人,分布在美国、瑞士、中国、印度等地的微软研发中心。这群人要负责190万个开发工作项目,完成了近3,600万个程序代码库,累计数据量达到15.3TB。开发团队平均每个月会组建(Build)22万多次。

    过去——瀑布开发模式

    •瀑布开发模式,开发时程约2年

    •花3个月时间来定制长期计划。其中,部门主管需要订定5年产品计划,而产品经理则是要想象2年后的市场需求,来拟定2年后产品上市时的功能蓝图。然后再设定多个里程碑(如图M1、M2,会发布一个对应的测试版本)区分开发阶段,每阶段内先开发程序代码,再进行测试与功能稳定,达成里程碑后发布一个顾客可用的版本。工程师们再依每一个里程碑估算自己的工作进度,并修正产品进度,来计算出2年后的哪一天能发布产品。

    •每一个里程碑阶段内还得设定程序代码开发完成的时间点(Code Complete),因为得预留时间作为测试工作和功能稳定调校,微软过去至少会预留两倍的程序代码开发所用的时间。多数情况是,微软工程师很快就完成程序代码的开发,反而是花了很多时间让功能稳定,例如整合不同功能间的冲突或整合。

    image

    现在——敏捷开发模式

    •采用敏捷开发模式,每三周为一个Scrum敏捷开发的Sprint(冲刺)周期,每次Sprint结束后要发布一个VS版本,试用一周后发布给使用者

    •开发与测试工作合而为一,转变成持续测试、持续整合的开发模式

    •微软也不再制订产品的5年计划了,而是缩短为只订定每6个月的计划,也就是两季长的计划,并每6个月进行市场或竞争对手评估,让产品能因应市场最新变化。另外还会订定一个18个月后要实现的产品愿景,来规划如软件架构调整或本质性需求调整等需要较长时间作业的目标

    image

    改变

    image

    image

    image

    image

    当然还有一些其他的改变,本篇就不一一列举了,比如测试团队缩小了,以前需要配备与开发团队规模相当的测试团队。

    快鱼法则

    先歇一会,又到了说书时间了。

    看完了Visual Studio团队的故事,我们再来看一个故事:

    有两个人在树林里过夜。早上,突然树林里跑出一头大黑熊来,两个人中的一个忙着穿球鞋。另一个人对他说:“你把球鞋穿上有什么用?我们反正跑不过熊啊!”忙着穿球鞋的人说:“我不是要跑得快过熊,我是要跑得快过你。” 这个故事给我两点启迪:

    • 我们面对的世界,是一个充满变数并且竞争非常激烈的世界,比跑得快不快,很可能成为决定成功与失败的关键。
    • 以往,“大鱼吃小鱼”以往被视为常理,可是在信息社会的市场竞争中,往往不是大鱼吃小鱼,而是快鱼吃慢鱼。这就是快鱼法则。

    天下武功无坚不破,唯快不破!——火云邪神

    看完故事,我们再看点实际的。比如下方的企业,在快鱼法则中体现的淋漓尽致:

    imageimageimageimageimage

    快鱼法则在互联网服务上的体现

    • 市场在变化,有太多不确定的因素
    • 需求变化不可避免
    • 抢先战略——商机是有限的
    • 追求创新
    • 需要快速响应用户的变化
    • 持续关注用户行为以及用户体验

    知道了快鱼法则,我们再来谈谈敏捷。

    为什么要敏捷?

    降低项目风险

    • 缩短反馈周期
    • 减少误解(沟通)
    • 降低修正错误的代价

    确保正确的方向

    • 可用的软件
    • 用户验证
    • 适应变化

    总的来说,就一个字——“变”,适应变化。

    弱弱的说一句,对于公司来说,这玩意儿就是为了最大限度的挖掘程序员的潜力,并且提高效率以及规避风险,最终就是节约公司成本。

    什么是敏捷?

    image

    关于Scrum和XP

    前面说了敏捷它是一种指导思想或开发方式,但是它没有明确告诉我们到底采用什么样的流程进行开发,而Scrum和XP(即极限编程,它强调把它列出的每个方法和思想做到极限、做到最好,而它所不提倡的,则一概忽略(如开发前期的整体设计等))就是敏捷开发的具体方式了,你可以采用Scrum方式也可以采用XP方式;Scrum和XP的区别是,Scrum偏重于过程,XP则偏重于实践,但是大部分情况下,两者是结合一起应用的,不过我们侧重于说Scrum。

    Scrum的英文意思是橄榄球运动的一个专业术语,表示“争球”的动作;把一个开发流程的名字取名为Scrum,我想你一定能想象出你的开发团队在开发一个项目时,大家像打橄榄球一样迅速、富有战斗激情、人人你争我抢地完成它,你一定会感到非常兴奋的。而Scrum就是这样的一个开发流程,运用该流程,你就能看到你团队高效的工作。

    简单的来说:

    XP说:除了编程,什么事也不要打扰我(极限编程)!客户甲,你的测试工作Delay了(客户也是开发中的一员)!

    Scrum说:大家都是一条船上的人啦,都利索点划(团队对项目负责)!上次TM才起步就翻船了,这次请大家按照我们上次总结的划法配合好(反思)!划到前面那个岛,大家就休息下,然后总结下这次的经验还有看看接下来划到哪(迭代、评审、回顾、规划)!…

    Scrum开发模型

    image

    产品开发反思

    了解了敏捷开发,那么,我们如何走向自己的敏捷呢?

    也就是,我们应该如何来提高开发效率?如何来保障软件质量?如何快速响应市场?

    敏捷不是说出来的,是干出来的!Go!

    走自己的敏捷之路

    如我开篇所说,敏捷管理不可复制,我们需要走出自己的敏捷之路。每一个团队在初始阶段情况都不同,比如我们团队,存在以下问题:

    1.大家对敏捷了解不多

    2.单元测试大多还不会写,而且当前架构并不利于单元测试,那么测试驱动开发我们需要根据我们的情况逐步渐进

    3.持续集成我们还难以做到完善,但是可以初具规模

    4.会议我们会增加,但是更多的强调的是随时沟通,如果有需要演示或者相对严谨的,我们才会召开会议

    5.结对编程目前是不可能的

    6….

    总之,我们肯定无法做到很严格的敏捷开发,那么我们就开始我们自己的敏捷之旅吧。

    改变观念——主动接受需求的改变而不是拒绝

    对于需求变更,说实话,我的心里是拒绝的——一方面,我们尽可能的在细化需求,挖掘需求,以及复杂设计,另一方面,我们亦是尽可能的确认需求,自然是不太乐意接受这种需求变更。因为每一次的变更都需要我们付出很大的精力。

    然而,产品的方向,谁都无法把控。我们一次次的拒绝,实际上最终还得一次次接受。我们必须转变这种心态,而是应该接受合理的需求,同时欢迎并积极引导用户反馈,来不断的完善我们的产品。

    最后,我们需要知道一点:改变需求是好事情,因为这些改变意味着我们更了解市场需求。

    快速迭代

    在之前,我们总需要很长时间(比如V1耗时大半年)才能发布一个版本,而且这个版本还是在遵循业务或者我们的理解的基础上开发的版本。而现在,我们需要快速迭代,来不断的交付可用的产品。

    什么是迭代?迭代是指把一个复杂且开发周期很长的开发任务,分解为很多小周期可完成的任务,这样的一个周期就是一次迭代的过程;同时每一次迭代都可以生产或开发出一个可以交付的软件产品。

    敏捷测试——测试驱动开发(TDD)

    我们总是在抱怨没有测试人员,事实上我们现在招聘测试人员也是很不划算的,因为测试人员的工作量很难饱和,我们并没有需要持续测试的任务交给他们。但是我们确实很需要测试,因为Bug总是层出不穷,而且很容易重复出现,尤其是当我们在发布版本前集中测试时,Bug总是让我们改到崩溃。

    确实,在传统测试中,开发人员负责编码,测试人员负责质量验收,测试人员是软件质量的最后一道防线。那么现在起,在我们的敏捷开发中,系统设计、编码、单元测试、开发测试、重构等关键任务都需要我们自己(开发人员)来完成,以保证持续的、快速的业务价值交付。也就是,我们以后需要自己来做测试,除了编写单元测试,手工测试也是我们份内的事情。因此,后面招人也会优先考虑招聘开发人员。

    注意:在持续集成时,会运行所有的单元测试。这实际上提高了开发者的开发效率,因为单元测试可以有效的帮助开发人员发现代码中的逻辑错误。

    当然,产品达到一定规模的时候,独立测试人员也是需要的。他们可以来全面的验证和检查一个系统,以及提供自动化测试工具的支持,进行性能测试、负载测试、安全性测试等。

    image

    产品自动化测试反思

    我们目前的情况并不适合大规模的自动化测试,我们只能着手以下几点:

    1.简化手工测试(比如自动造数据等等),如果需要花费很多工作量来编写的单元测试,那目前还是以手工测试代替

    2.从架构级别增加对一些常用的API的单元测试,保证架构中主体API的正确,便于架构重构

    3.在后续的设计中或者系统下个版本时,使用利于搭建单元测试的架构

    持续集成

    持续集成正是针对上述一系列问题的一种软件开发实践,它倡导团队开发成员必须经常集成他们的工作,甚至每天都可能发生多次集成。而每次的集成都是通过自动化的构建来验证,包括自动编译、发布和测试,从而尽快地发现集成错误,让团队能够更快的开发内聚的软件。

    image

    要素

    1.统一的代码库

    2.自动构建

    3.自动测试

    4.每个人每天都要向代码库主干提交代码

    5.每次代码递交后都会在持续集成服务器上触发一次构建

    6.保证快速构建

    7.模拟生产环境的自动测试

    8.每个人都可以很容易的获取最新可执行的应用程序

    9.每个人都清楚正在发生的状况

    10.自动化的部署

    原则

    1. 所有的开发人员需要在本地机器上做本地构建,然后再提交的版本控制库中,从而确保他们的变更不会导致持续集成失败。

    2. 开发人员每天至少向版本控制库中提交一次代码。

    3. 开发人员每天至少需要从版本控制库中更新一次代码到本地机器。

    4. 需要有专门的集成服务器来执行集成构建,每天要执行多次构建。

    5. 每次构建都要100%通过。

    6. 每次构建都可以生成可发布的产品。

    7. 修复失败的构建是优先级最高的事情。

    8. 测试是未来,未来是测试

    我们的持续集成流程

    image

    生成列表:

    image

    失败结果:

    image

    成功结果:

    image

    推行每日站立会议

    我们过去总是很死板的在项目经理和开发人员之间互动——这个任务你做的如何了?那么现在,我们需要这么一个短会:

    目的:

    • 团队成员间工作进度的沟通和协调;
    • 帮助团队聚焦于每日活动,并且便于更新任务板和燃尽图;
    • 细化任务,尽可能的将任务具体到天,让大家都明确知道今天应该做什么!

    时间:每日早晨10点,时长控制在15分钟左右

    内容:

    • 从上次站立会议到现在,你完成了什么?
    • 从现在到下次站立会议,你将要做什么?
    • 你遇到什么阻碍,需要其它人如何帮你?

    注意:

    1. 不要迟到,延时,或者坐下
    2. 不要在会议中讨论技术细节以及沟通需求。

    提示:团队成员在聆听他人发言时,都应该想这个问题:“我该怎么帮他做得更快?”

    简单

    产品伊始,我花了一个月的时间来制定了插件式架构,实际上现在这个架构看起来已经不太适合当前的业务。需求一直在变,我们尽可能的去设计与开发,但是现在,很多设计只是当时看起来很好罢了。我们抱怨过设计缺陷以及架构缺陷,甚至“抱憾终身”,那么现在开始,我们不再过多的设计——而是注重规范与重构。

    我们不可能预期后面需求会如何变化,所以不可能一开始就构建一个完美的架构来适应以后的所有变化。因此敏捷团队不会去构建明天的软件,而把注意力放在如何通过最简单的方法完成现在需要解决的问题。如果已经预计到了肯定存在哪些需求扩展点,我们在一开始是否需要考虑呢?这时我们需要根据自己的理解去决定是否考虑,如果深信在明天发生了这个问题也可以轻易处理的话,那么就最好先不考虑。

    因此在后面的开发中,我们的法则就两个字——简单。简单设计,简单架构,简单编码还有简单评估。

    另外一点,我们需要注意的是,数据库我们也不再做过多的设计——也就是我们需要认同一点,数据库的设计是随时可以变更的,也就是我们几乎不进行预先设计。

    微博上有人说“好的架构是进化来的,不是设计来的”。的确如此,其实还可以再加上一句“好的功能也是进化来的,不是设计来的” 。——《淘宝技术这十年》

    注意代码规范,提高代码的可读性

    简单并不意味着没有规范。简单和规范的目的都是为了提高代码的可阅读性,提高代码的可阅读性是为了便于代码修改以及重构——也就是增加代码的可维护性。

    如下图所示,在有条件的情况下,我们会逐步实行以下步骤:

    image

    如果说提高代码的可读性是为了便于重构,那么自动化单元测试则是重构的保证。

    利用反馈以及真实的数据来完善产品

    如下图所示,我们已经开发了很多功能,我们尽可能的使每个功能完善。但是实际上,我们并不清楚用户喜欢哪些功能,这些功能的用户体验具体如何,甚至是在用户的环境下能不能用!

    那么现在开始,我们必须以真实的反馈以及真实的使用数据来不断的完善我们的产品。

    image

    下面是反馈流程:

    image

    迭代规划会议

    迭代规划会议是指在每轮迭代开始时进行的规划会议,定义本轮迭代的目标,承诺本轮迭代中要完成的工作,提前识别和评估可能出现的风险,并通过合理的估算调整项目的迭代范围。

    目标

    • 制定合理的迭代范围和目标
    • 明确迭代的开发任务

    要求

    • 如无特殊原因,产品团队利益相关者均需参加
    • 会议召开前,会通知所有利益相关者具体开会时间

    内容

    • 这里我要求将反馈审批与讨论放在这里进行,以减少大型会议的次数
    • 会议只讨论下次迭代内容以及任务优先级,并不涉及工作量的评估以及时长的评估

    会议结果

    明确迭代范围与目标,明确此次迭代的开发任务

    评审会议

    在每次冲刺结束,我们都需要进行一次评审会议,让团队向产品负责人和利益相关者展示已完成的功能。

    也就是“所有的sprint(冲刺)都结束于演示”!

    目标:

    1.加强团队的自我认可。

    2.展示功能、回答利益相关者对展示的疑问并记录所期望的更改与反馈。

    3.评审会议可以吸引相关利益者的关注,让其他人了解团队在做些什么,并得到重要反馈。

    4.做演示也会迫使开发团队真正完成一些工作(比如那些完成了99%的功能)。

    时间:每一次冲刺完成时根据情况召开。

    要求:

    1.团队成员均可主持。必须准备PPT,可以很粗糙,但是必须有条理。

    2.确保所有人员都清晰目标,如果有人对产品不知道,则花几分钟来进行描述。

    3.团队根据本次迭代内容,逐个地介绍这次 Sprint 的结果,和演示新功能。

    4.会议过程中,需要记录需求变更、新想法、新需求、Bug或问题以及障碍。

    5.如果功能无法演示,则以报表或者报告甚至其他任意形式证明。

    会议结果

    对这次 Sprint 的结果和整个产品的开发状态的共识

    注意:

    • 让演示关注业务层次,不要关注技术细节。注意力放在“我们做了什么”,而不是“我们怎么做的”
    • 有的sprint可能会包含很多bug修复等功能,在评审会议中不要演示太多一大堆细碎的bug修复,除非这个很重要。

    事实上,后续我们还可以加上估算会议以及sprint回顾会议,但是目前我想将这些内容在日常探讨中完成。除非有必要,我们才会单独召开。

    经常反省

    image

    上图是孔子,曾经子曰….,这里就不赘述了。

    敏捷不能照抄照搬,因此,我们需要经常在如何才能更有效地工作方面进行反省,然后相应地对自己的行为进行调整。

    由于很多不确定性因素会导致计划失效,比如项目成员增减、技术应用效果、用户需求的改变、竞争者对我们的影响等都会让我们作出不同的反应。而敏捷不是基于预定义的工作方式,而是基于经验性的方式,对以上这些变化,我们必须通过不断的反省调整来保持团队的敏捷性。比如,反思会议。

    反思会议

    根据项目需要举行。其目的不是为了找到治愈方案,而是要发现哪些方面需要改进。项目成员均可召开与推进。

    要求:

    1.从过去中学习,指导将来。

    2.改进团队的生产力。

    3.轮流发言。每个人都有机会在不被人打断的情况下讲出自己的想法,他认为什么是好的,哪些可以做的更好,哪些需要改变。

    注意:

    1.不要让管理层人员参与会议。

    2.不要在团队之外讨论找到的东西。

    会议内容:

    1.过去哪些做的不错?哪些应该改进?

    2.我们能做什么?哪些不在我们掌控之内?

    3.意见交流

    始终保持让团队坐在一起

    现在,我们都是坐在一起的,但是今后我们会始终保持这种状态。

    “一起”意味着:

    • 互相听到:所有人都可以彼此交谈,不必大声喊,不必离开座位。
    • 互相看到:所有人都可以看到彼此,便于协作。后续还可以考虑放置一个实体的任务板,便于团队随时能够看到进度。
    • 隔离:如果你们整个团队突然站起来,自发形成一个激烈的设计讨论,团队外的任何人都不会被打扰到。反之亦然。
    • 随时沟通:比如我需要协助
    • 不过于依赖文档和工具:比如任务在Worktile上分配完毕,也给他们打个招呼吧。

    保持可持续的开发速度/精力充沛的工作

    敏捷开发讲究的是高效工作,而且是持续的高效工作。那么我们需要注意以下几点:

    1.尽可能避免加班(几乎所有的敏捷开发模式都反对加班,因为加班工作在软件开发中会降低生产率,而且会降低产品质量。我们目前还无法保障不加班,但是我们要尽可能的避免加班——将当天的事情在工作时间内完成)。

    2.上班时间保持充沛的精力(比如早睡早起,喝点咖啡等等)

    3.集中精力

    精诚合作的团队理念

    • 产品不属于我个人,整个团队都必须对其负责。那么在需求评审、需求评估、迭代规划、开发交流的时候,大家都应该积极参与
    • 必须达成共识,必须明确每次迭代的内容,而且知晓自己的和整个产品的进度
    • 每个人不再是单独的个体,在交流的时候,你不仅仅只关心自己相关的模块,你还得为大家出谋划策,甚至是帮忙
    • 积极沟通,当然文档不是必须的,但是有准备的沟通是必须的!

    不断的提升自己

    就如上篇所说,系统设计、编码、单元测试、开发测试、重构等关键任务都需要我们自己(开发人员)来完成,也就是我们必须得肩负起更多的使命——我们不再是只关注开发,只专注于自己的开发任务,我们是全能的(测试、开发、设计甚至管理)。

    image

    每周讲座

    目的:鼓励大家交流、分享、学习甚至是反思。

    讲座内容:技术、经验、心得、建议、产品与团队思考均可,亦可召开反思会议。

    机制:每周一次,一次仅限一人,轮流讲座,次序可以根据需要调整。

    时间:每周周四下午,时间和日期可以更改,但是需要提前通知。如非客观原因,否则不能取消。

    要求:必须准备PPT以及演讲素材。

    时长:半小时左右。

    讲师:团队成员。

    参与人:无限制,自愿参加 
    讲座完成,需要将PPT和相关资料附加到相关任务,后续统一归档到Sharepoint相关文档库。

    规范以及梳理意识

    无论是自己,还是针对整个产品,我们都必须要有规范以及梳理意识,这个意识不能单靠我个人来推动,需要大家自发的来遵守以及完善。目前我们做到了以下几点,但是我希望大家在遵守的前提下,反过来推动这些机制的完善,并且相互监督:

    image    

    无规矩不成方圆,团队还将试行行为规范和准则,实行扣分制。具体请查看相关文档说明。(后续会介绍)

    最后,嗯,比如长期提供咖啡

    其实说了这么多,还是这句比较实在。

    最后

    敏捷开发之路,我们还需不断摸索前进。

    我知道我的未来不是梦
    我认真的过每一分钟
    我的未来不是梦
    我的心跟着希望在动

    ——张雨生《我的未来不是梦》

  • 相关阅读:
    1、Elasticsearch教程-从入门到精通
    3、ik分词器
    2、ElasticSearch的安装
    svn操作
    2020-10
    编写第一个linux驱动
    字符设备驱动
    Linux下/dev和/sys/class的区别
    latex
    Qt
  • 原文地址:https://www.cnblogs.com/codelove/p/4498850.html
Copyright © 2011-2022 走看看