2013年7月17日星期三

敏捷活动中的系统思考

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
敏捷活动中的系统思考  阅读原文»

敏捷活动中的系统思考

1 引言

近期,我所在的组织(软件研发单位)开始了轰轰烈烈的由传统的管理方式向敏捷转型工作。我们希望通过敏捷,提高研发效率和产品质量。但是,随着时间的推移,发现敏捷并非良药,上上下下对敏捷的热情逐渐消退,敏捷正逐渐走向"灭亡"。

是敏捷对提高效率没有帮助吗?是敏捷在传统企业里面水土不服吗?怎样才能在做好敏捷呢?

本文试图从实际出发,结合系统思考,来反思我们的敏捷。希望这个反思过程,能够给准备进入敏捷,或者正在敏捷中纠结的团队提供参考。

2 敏捷之初――增强环路

image

图1 敏捷之初――增强环路

敏捷开始之初,领导热情高涨,敏捷推行风风火火,是一个典型的增强环路。(该模型的具体信息,可以参考《第五项修炼》)。

敏捷试点,培训,敏捷推广――敏捷活动"全面"铺开。

开发和测试不打架了,沟通效率明显提升,里程碑的压力被迭代活动稀释了――团队自组织程度提高明显。

需要特别强调的是,在敏捷活动中,管理实践和技术实践会有很多具体的问题。这些问题会制约敏捷活动的进行,不在本环路中体现,后续有机会再开帖子讨论。

3 敏捷之中――成长上限

虽然敏捷有诸多好处,但是,我需要很遗憾的告诉大家,跟所有的增强环路一样,一定有一个平衡环路制约增强环路的成长空间。如图2所示。在敏捷到一定程度时。团队自组织程度提高,工作过程中诸如详细设计、同行评审、内部故障等等表现形式和传统的软件管理大相径庭。对传统管理带来了威胁:

1) 基层组织自我管理――管理层架空了;

2) 敏捷详细设计等研发过程不能在传统的系统中登记――管理过程对象隐形了。

和大多数公司一样,作者所在的组织的管理层,对传统管理持保守态度。他们希望管理可控,他们希望管理架构不要做大的变化;他们也希望敏捷做的越来越好,甚至希望能在冬天里燃气一把火――这在某种程度上加速了敏捷活动在组织中的消亡。因为成长上限模型决定了这一结果:当平衡环路发挥较强作用时,加速推动增强环路,不但不会取得很好的效果,甚至有可能引起增强环路反转。

image

图2 敏捷之中――成长上限

现实的系统往往是很复杂的。作者所在的组织。在敏捷推行到一定程度时,平衡环路发挥作用,同时内部力量继续猛烈的推动增强环路。敏捷活动中出现了三种情况:

1) 有追求型――想尽一切办法,延缓甚至解除平衡环路对团队自组织程度的制约

2) 因势利导型――一方面降低对传统管理的威胁,一方面推动敏捷,稳打稳扎

3) 放弃型――不搞敏捷了,爱咋咋地

下面我们用三个小节详细展开。

image

图3 有追求型

有追求型的敏捷团队这样的特点:

有一个强势的团队领导者,拥抱敏捷,对敏捷理解很深,可以跟管理层叫板。

通过强势的敏捷团队领导者的操作,传统管理层的威胁对团队自组织程度的影响大大延迟。敏捷活动这个增强环路可以在相当长一段时间,获得成长空间。

在有追求型的团队里面。还有一些要素需要注意

1) 需要优秀的敏捷实践指导。这样可以及时解决敏捷实践中的管理和技术问题(例如TDD),提高团队的敏捷积极性。

2) 一个合适的项目。那种工期紧,现场问题多就算了。合适项目最好是只用一种编程语言,没有太大工期和现场压力的技术型项目。

3) 几个技术骨干。如果全部是技术骨干,对其他项目会有较大影响。如果全部是新手,肯定也是玩不转的。

4) 对敏捷中的实际问题,不回避。敏捷是一种能力,需要通过实践,踏踏实实做出来,敏捷来不得半点忽悠。

很可惜,作者所在的团队不是有追求型团队。对于有幸在传统自组织中,进入到有追求型团队的兄弟,希望好好把握,在不久的将来,能够得到敏捷的精髓,进而诞生推动更多有追求的敏捷团队诞生。

在因势利导型的团队中,没有一个强势领导。换言之,就是对敏捷活动的支持力度跟上面是一致的。如果自组织团队程度影响到传统管理,他会毫不犹豫的和传统管理站在一起。

在因势利导型团队里面,一般会有两种手段来推进敏捷。

方式1:做好传统管理要求的事情

方式2:延迟传统管理对团队自组织程度的影响

上图:

image

图4 因势利导型

在方式一中,我们把传统管理要求的平时、设计做好,使得管理层可以"看到"传统管理的对象,从而降低对传统管理的威胁,给敏捷活动创作空间。

在方式二中,我们将传统管理的威胁,通过多层管理过滤和旁路模式(分给其他团队)的方式,延迟传统管理的威胁。这种方式,和有追求型的敏捷团队最大的区别在于延迟的力度或者时间。在本类型中,这个延迟相对来说,是比较"脆弱"的。

放弃型团队是这样一种状况:管理层驱动,团队在没有做好准备的时候"被敏捷";团队领导和团队成员缺乏对敏捷的深入理解和认同。当敏捷活动遇到困难或者团队自组织程度收到传统管理的威胁时,团队敏捷积极性急剧下降,最后就是不了了之。

在这样的团队,基本上就是浪费时间,唯一的收获可能就是对敏捷的"恶感"。

从成长上限模型可知,通过杠杆解发力,可以事半功倍的解决问题。在敏捷活动中,杠杆解即"管理层的目标",如图5所示。

image

图5杠杆解

需要说明的是,所谓的杠杆解对应的管理层,一般不是公司老总,而是能够对敏捷的组织形式,资源分配,考核等有决策权的管理者。

当然,不是说敏捷跟公司老总没有关系。实际上,敏捷跟公司老总有关系,关系在哪儿呢?在于企业文化。我个人认为,敏捷是有适合的企业文化的。传统的指令型(老大绝对正确性)企业,搞敏捷是有很大风险的。如果敏捷决策管理者对敏捷理解正确,那么,一切可能会朝着OK的方向进行。否则,就有很大可能产生巨大的浪费,甚至造成公司挂掉。

因此,在一个组织里面,要搞好敏捷,首先要搞定管理者。

我们假设大部分企业都是指令型企业(这可能是中国软件研发的普遍状况)。那么在敏捷开始之初,一定要仔细考评敏捷管理决策者对敏捷的理解。如何考评呢:

1) 读过《人件》,《人月神话》

2) 理解敏捷宣言,敏捷的原则

3) 理解敏捷实践,包括实践的普遍性和特殊性。敏捷的技术实践,在特殊性方面表现的尤为突出。如果一个组织有多重技术架构,那么,就会需要对应的技术实践。甚至,有些产品可能压根就做不了某些技术实践,比如TDD。

4) 理解敏捷的组织,评价

5) 理解敏捷适应的环境(高级要求)。不是每一个产品都适合敏捷。

关于敏捷,网上有很多前辈做了很多精彩的论述。本文仅从系统思考的角度对敏捷做了一些简单的思考。希望对大家有一点点?div style="border-bottom:1px solid #aaa;margin-bottom:25px">python+Django实现Nagios自动化添加监控项目  阅读原文»

用户名:david_bj 文章数:21 评论数:7
访问量:4715:974:248:2 注册日期:2011-12-21

最近机房刚上了一批机器(有100台左右),需要使用Nagios对这一批机器进行监控。领导要求两天时间完成所有主机的监控。从原来的经验来看,两天时间肯定完成不了。那怎么办?按照之前的想法,肯定是在nagios配置文件逐一添加每台客户端的监控信息,工作量巨大。突然,想到一个想法,是否可以通过脚本来实现批量对主机进行监控,也就是运维自动化。

写脚本,最重要的就是思路。思路压倒一切,经过思考最终决定就这么做了。先贴出来一张网路拓扑图:

整个过程可以分为三部分。

  • cmdb端:主要用来实现对数据的收集,采用两个API,一个是提供给客户机的API。用于将客户端的数据上传的cmdb服务器;另外一个API是nagios通过此API可以得到要监控主机的信息,然后对该信息进行整理,做成nagios监控模板。

  • Client端:通过Python脚本收集本机器要监控的软硬件信息,然后通过cmdb端提供的API接口将数据上传到cmdb端的数据库。

  • Nagios端:通过cmdb端提供的API接口实现对cmdb收集到的信息进行抓取,然后将数据写入到模板,最后copy到naigos指定的objects目录,最终实现对客户机的监控。

这三部分最重要的应该是CMDB端。接下来通过安装django和编写API接口实现cmdb可以正常工作。可以将cmdb端分为三个步骤来完成:

  • 安装django

  • 配置django

  • 编写API接口

首先来进行安装django:

在安装django之前首先应该安装python(版本建议2.7.)

  1.下载django软件包    可以到django官方网站下载最新django软件包(https://www.djangoproject.com).  2.解压缩并安装软件包     tar -zxvf Django-1.5.1.tar.gz     cd Django-1.5.1     python setup.py install  

创建项目和应用:

  1.创建一个项目  python startproject simplecmdb  2.创建一个应用  python startapp hostinfo  

配置django:

1.修改setting.py

  • DATABASES = {'ENGIN':'django.db.backends.sqlite','name':path.join('CMDB.db')} #使用的数据库及数据库名

  • INSTALLED_APPS =(hostinfoINSTALLED_APPS = ('hostinfo')

  • INSTALLED_APPS = ('hostinfo') #应用的名称

2.修改urls.py

  • url(r'^api/gethost\.json$','hostinfo.views.gethosts'), #nagios客户端访问API接口地址

  • url(r'^api/clooect$','hostinfo.views.collect'), #客户端访问API进行上传数据的API

  • url(r'^admin/',include(admin.site.urls)), #django后台管理登入url

  • from django.contrib import admin

  • admin.autodiscover()

3.修改项目hostinfo下的views.py

代码如下:

  # Create your views here.  #包含以下模块  from django.shortcuts import render_to_response  from django.http import HttpResponse  from models import Host, HostGroup  #包含json模块  try:      import json  except ImportError,e:      import simplejson as json  #用来接收客户端服务器发送过来的数据  def collect(request):      req = request      if req.POST:          vendor = req.POST.get('Product_Name')          sn = req.POST.get('Serial_Number')          product = req.POST.get('Manufacturer')          cpu_model = req.POST.get('Model_Name')          cpu_num = req.POST.get('Cpu_Cores')          cpu_vendor = req.POST.get('Vendor_Id')          memory_part_number = req.POST.get('Part_Number')          memory_manufacturer = req.POST.get('Manufacturer')          memory_size = req.POST.get('Size')          device_model = req.POST.get('Device_Model')          device_version = req.POST.get('Firmware_Version')          device_sn = req.POST.get('Serial_Number')          device_size = req.POST.get('User_Capacity')          osver = req.POST.get('os_version')          hostname = req.POST.get('os_name')          os_release = req.POST.get('os_release')          ipaddrs = req.POST.get('Ipaddr')          mac = req.POST.get('Device')          link = req.POST.get('Link')          mask = req.POST.get('Mask')          device = req.POST.get('Device')          host = Host()          host.hostname = hostname          host.product = product          host.cpu_num = cpu_num          host.cpu_model = cpu_model          host.cpu_vendor = cpu_vendor          host.memory_part_number = memory_part_number          host.memory_manufacturer = memory_manufacturer          host.memory_size = memory_size          host.device_model = device_model          host.device_version = device_version          host.device_sn = device_sn          host.device_size = device_size          host.osver = osver          host.os_release = os_release          host.vendor = vendor          host.sn = sn          host.ipaddr = ipaddrs          host.save()       #将客户端传过来的数据通过POST接收,存入数据库          return HttpResponse('OK')   #如果插入成功,返回'ok'      else:          return HttpResponse('no post data')  #提供给NAGIOS 的API  def gethosts(req):      d = []      hostgroups = HostGroup.objects.all()      for hg in hostgroups:          ret_hg = {'hostgroup':hg.name,'members':[]}          members = hg.members.all()          for h in members:              ret_h = {'hostname':h.hostname,    #API接口返回的数据                  'ipaddr':h.ipaddr              }              ret_hg['members'].append(ret_h)          d.append(ret_hg)      ret = {'status':0,'data':d,'message':'ok'}      return HttpResponse(json.dumps(ret))  

4.修改model.py 文件

代码如下:

  from django.db import models  # Create your models here.  #插入数据库的Host表,主要存储客户端主机的信息  class Host(models.Model):      """store host information"""      vendor = models.CharField(max_length=30,null=True)      sn = models.CharField(max_length=30,null=True)      product = models.CharField(max_length=30,null=True)      cpu_model = models.CharField(max_length=50,null=True)      cpu_num = models.CharField(max_length=2,null=True)      cpu_vendor = models.CharField(max_length=30,null=True)      memory_part_number = models.CharField(max_length=30,null=True)      memory_manufacturer = models.CharField(max_length=30,null=True)      memory_size = models.CharField(max_length=20,null=True)      device_model = models.CharField(max_length=30,null=True)      device_version = models.CharField(max_length=30,null=True)      device_sn = models.CharField(max_length=30,null=True)      device_size = models.CharField(max_length=30,null=True)      osver = models.CharField(max_length=30,null=True)      hostname = models.CharField(max_length=30,null=True)      os_release = models.CharField(max_length=30,null=True)      ipaddr = models.IPAddressField(max_length=15)      def __unicode__(self):          return self.hostname  #主机组表,用来对主机进行分组  class HostGroup(models.Model):      name = models.CharField(max_length=30)      members = models.ManyToManyField(Host)  

5.修改admin.py文件

  #from models import Host, IPaddr  from models import Host, HostGroup  from django.contrib import admin  #设置在django在admin后天显示的名称  class HostAdmin(admin.ModelAdmin):      list_display = ['vendor',          'sn',          'product',          'cpu_model',          'cpu_num',          'cpu_vendor',          'memory_part_number',          'memory_manufacturer',          'memory_size',          'device_model',          'device_version',          'device_sn',          'device_size',          'osver',          'hostname',          'os_release'          ]  #在django后台amdin显示的组名称  class HostGroupAdmi

阅读更多内容

没有评论:

发表评论