实施项目--你明白软件的价值和个人的价值么?

  在2013即将结束的最后一个月里,我跑客户的时间时间达到了26天,作为一个技术出身的我这是非常不可思议的,在多年前我敢都不敢想! 在历史上一个月里我连续工作的天数也就27天,当然这是呆在公司办公室里,负责码代码,不会与直接客户面对面接触的(目前大多数技术人员都是如此)。这段时间的持续改变让我不得不深思!

 

  一. 代码的价值

    案例1:

    最近有个项目实施难度有点大,当然我本身是技术出身,所以有时候还是比较有优势,因为可以当场为客户解决问题。我们是为一家生产型企业实施一个生产仓库管理系统,现在条件比较复杂,反正就是涉及到生产,出入库等!实施到一个出库的时候,有个功能是这样的:

    客户要求公司客服人员直接查询仓库库存,然后根据订单配货,这个配货是可以合并多个订单的,做好配货单要系统生成一个拣货清单[也就是告诉仓库人员到哪里去拿货,在货架哪里,在货架第几层,是否需要拆托盘,是否要拆箱等等],仓库人员拿着清单直接到仓库将取货让后用叉车搬到代发货区域。然后发货人员拿着PDA(非常老式的那种)去扫描箱码或者托盘条码进行配货校验,最后打印发运标签(每个箱子上都要贴这种标签,每个单子估计都有几百上千箱货)。 

    现在有个问题就是这搬出来的货要自动分配到不同的订单中去,而且要满足订单情况。

    比如A订单 产品P 需要数量 16,000 ; B 订单需要产品 P 数量为 54,000; C订单需要产品P数量 16,000; C 订单需要产品P1  2,000; 

    仓库拣货数量为: 16,000+54,000+16,000 (P产品) ; 2,000 (P1产品)

    P产品包装: 标准包装5,000   P1产品包装: 标准包装 600

     实际拣货为: 4*5000(整箱) + 10*5000(整箱)+ 2*5000(整箱) + 2000(零箱)+ 4000(零箱) --P产品;  3*600(整箱)+200(零箱) 

     那上面分配货品有很多种分配方式,不同的订单可以共箱(在一个箱子上贴两个标签 200 + 400 分别是不同的订单)。

    至于具体情况如何,这个也不是一会能够描述清楚的,做过拣货的朋友应该清楚:

    问题是我写了一段代码,自动分配拣货的,大概花了我4天左右的时间,总共代码行估计接近一千行了,代码部分如下:

int qty = detail.Qty;
                        int fullBoxNum = packageNum != 0 ? qty / packageNum : 0; //理论整箱箱数
                        int sinQty = packageNum != 0 ? qty % packageNum : 0; //理论零箱数
                        int sinBoxNum = sinQty == 0 ? 0 : 1; //理论零箱箱数
                        string PO = detail.OrderNum;//PO
                        ShipLableEntity ship = null;

                        /**
                         * 当拣货得到的箱子中整箱数大于0的情况:
                         * 当拣货得到的箱子中整箱数==0的情况: 说明所有的拣货都要从零箱中去组合得到
                         * */
                        if (listFullBoxes.Count > 0)
                        {
                            //当理论拣货整箱箱数大于0 且 实际整箱也大于0的时候
                            if (fullBoxNum > 0)
                            {
                                //如果理论总箱数小于或等于实际总箱数则扣除实际理论箱数,并且判断是否有零箱
                                if (fullBoxNum <= listFullBoxes.Count)
                                {
                                    ship = FormatShipLable(product, PO, outNum, listFullBoxes.First(), orderEntity, index, fullBoxNum, listDefault, listBills);
                                    listShipLables.Add(ship);
                                    listFullBoxes.RemoveRange(0, fullBoxNum);
                                    index++;
                                    //判断有零箱的情况,找到最适合的箱数,没有就要拆箱分组. 如果没有零箱什么都不用处理 所以不需要else
                                    if (sinBoxNum == 1)
                                    {
                                        //如果存在理论零箱的时候,先要实际零箱的箱数是否大于0且零箱的总数也大于理论零箱的数量
                                        if (listSinBoxes.Count > 0 && listSinBoxes.Sum(a=>a.QTY)>=sinQty)
                                        {
                                            //升序排列,查找大于等于零箱数的第一个箱拆分
                                            listSinBoxes = listSinBoxes.OrderBy(a => a.QTY).ToList();
                                            OutBillEntity tempBill = listSinBoxes.Where(a => a.QTY >= sinQty).FirstOrDefault();
                                            //如果存在满足上面条件的箱,则需要拆分处理
                                            if (tempBill != null)
                                            {
                                                //如果数量刚好满足则直接生成标签 如果不满足则拆分为两个
                                                if (tempBill.QTY == sinQty)
                                                {
                                                    ship = FormatShipLable(product, PO, outNum, tempBill, orderEntity, index, 1, listDefault, listBills);
                                                    listShipLables.Add(ship);
                                                    listSinBoxes.Remove(tempBill);
                                                    index++;
                                                }
                                                else
                                                {
                                                    tempBill.QTY = tempBill.QTY - sinQty;
                                                    OutBillEntity billNew = new OutBillEntity();
                                                    billNew.LairdPN = tempBill.LairdPN;
                                                    billNew.CustomerPN = tempBill.CustomerPN;
                                                    billNew.StackBarCode = tempBill.StackBarCode;
                                                    billNew.BoxBarCode = tempBill.BoxBarCode;
                                                    billNew.QTY = sinQty;
                                                    ship = FormatShipLable(product, PO, outNum, billNew, orderEntity, index, 1, listDefault, listBills);
                                                    listShipLables.Add(ship);
                                                    if (tempBill.QTY <= 0)
                                                    {
                                                        listSinBoxes.Remove(tempBill);
                                                    }
                                                    index++;
                                                }
                                            }
                                            else
                                            {
                                                //如果不存在则需要组合得到,查询组合求和数量小于等于零箱的数量
                                                int zuQty = 0; //计算总和
                                                int sinIndex = 0; //满足条件之后停止的索引
                                                for (int i = 0; i < listSinBoxes.Count; i++)
                                                {
                                                    zuQty += listSinBoxes[i].QTY;
                                                    if (zuQty >= sinQty)
                                                    {
                                                        sinIndex = i;
                                                        break;
                                                    }
                                                }
                                                //如果刚好满足则生成相应的标签,并且删除
                                                if (zuQty == sinQty)
                                                {
                                                    for (int i = 0; i <= sinIndex; i++)
                                                    {
                                                        ship = FormatShipLable(product, PO, outNum, listSinBoxes[i], orderEntity, index, 1, listDefault, listBills);
                                                        listShipLables.Add(ship);
                                                        index++;
                                                    }
                                                    listSinBoxes.RemoveRange(0, sinIndex + 1);
                                                }
                                                else
                                                {
                                                    //删除之前的,最后一个拆分
                                                    int beforeQty = 0;
                                                    for (int i = 0; i <= sinIndex - 1; i++)
                                                    {
                                                        beforeQty += listSinBoxes[i].QTY;
                                                        ship = FormatShipLable(product, PO, outNum, listSinBoxes[i], orderEntity, index, 1, listDefault, listBills);
                                                        listShipLables.Add(ship);
                                                        index++;
                                                    }
                                                    tempBill = listSinBoxes[sinIndex];
                                                    tempBill.QTY = tempBill.QTY - (sinQty - beforeQty);
                                                    OutBillEntity billNew = new OutBillEntity();
                                                    billNew.LairdPN = tempBill.LairdPN;
                                                    billNew.CustomerPN = tempBill.CustomerPN;
                                                    billNew.StackBarCode = tempBill.StackBarCode;
                                                    billNew.BoxBarCode = tempBill.BoxBarCode;
                                                    billNew.QTY = sinQty - beforeQty;
                                                    ship = FormatShipLable(product, PO, outNum, billNew, orderEntity, index, 1, listDefault, listBills);
                                                    listShipLables.Add(ship);
                                                    index++;
                                                    listSinBoxes.RemoveRange(0, sinIndex);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            //如果实际零箱数为0 或者实际零箱数小于理论零箱数,那么就要拆整箱,因为实际整箱大于理论整箱所以拆整箱
                                            if (listFullBoxes.Count > 0)
                                            {
                                                OutBillEntity tempBill = listFullBoxes.First();
                                                tempBill.QTY = tempBill.QTY - sinQty;
                                                listFullBoxes.Remove(tempBill);
                                                listSinBoxes.Add(tempBill);
                                                OutBillEntity billNew = new OutBillEntity();
                                                billNew.LairdPN = tempBill.LairdPN;
                                                billNew.CustomerPN = tempBill.CustomerPN;
                                                billNew.StackBarCode = tempBill.StackBarCode;
                                                billNew.BoxBarCode = tempBill.BoxBarCode;
                                                billNew.QTY = sinQty;
                                                ship = FormatShipLable(product, PO, outNum, billNew, orderEntity, index, 1, listDefault, listBills);
                                                listShipLables.Add(ship);
                                                index++;
                                            }
                                        }
                                    }
                                }

智能拣货分配部分代码

    以上代码可以忽略不计,跑到客户那边实施这个功能(部分上线) , 当时我感觉很牛逼,因为我作为实施人员还在写代码 而且还搞定了,公司的其他技术人员没有搞定。 到客户现场使用之后,工厂工人说这个太慢了不好用,给他们领导反馈这个他们不会使用这个东西的,完全是浪费他们时间,上报到公司之后后果各位也想得出来,被客户噼里啪啦的说了一顿说做的东西不行怎么怎么。

    心理受到极大的创伤啊,自己辛辛苦苦弄出来的东西就这样一句话给抹杀了,实在是痛心。

OPEN  MyCursor FETCH NEXT FROM MyCursor INTO @RowNum,@Qty
    WHILE @@FETCH_STATUS=0
    BEGIN
        set @SumQty = @SumQty+@Qty
        IF @SumQty>=@Num + (@PackageQty * 5)
        BEGIN
            break
        END
        FETCH NEXT FROM MyCursor INTO @RowNum,@Qty
    END
    CLOSE MyCursor
    DEALLOCATE MyCursor--释放游标
    ;
    WITH TempTable AS
    (
        SELECT ROW_NUMBER() OVER (ORDER BY DCTime ASC,ID DESC) RowNumber,DCTime,ID,
        OrderNum,CusNum,CreateTime,LairdPN,CustomerPN,Qty,LocalNum,StackBarCode,BoxBarCode,HasStack,IsBlend,IsHalfBox,LairdNum,LairdBoxNum,IsFullStack
        FROM LocalProductRel
        WHERE LairdPN=@LairdPN AND CustomerPN=@CustomerPN
            AND IsLock=2 AND IsReject=2 AND IsRework=2 AND IsChange=2 AND IsOnlyCustomer=2
            AND LocalNum!='XF9-9-9' AND [StorageNum]='7112'
            AND Qty=@PackageQty
    )
    SELECT * FROM TempTable WHERE RowNumber<=@RowNum

优化部分代码

    回去之后又努力优化程序,大概又花了两天时间,速度提升了不少,再去客户那边操作人员满意OK,得到赞赏,心里美滋滋啊!

 

    仓库操作人员其实不懂计算机的,只会上QQ,看新闻什么的,编程什么的就是妄想之中的事情。所以你写的代码好与坏跟他们无关。上面的代码开始我认为自己写的很好,可事实不是这样的,客户不买你的帐,你写的再好客户又看不懂对他们来说毫无意义,一不会给他们减轻工足量反而增大了,二不能给他们美感(软件上没有美女),三不会给他加工资。

    第一段代码你写的再多,你花了多少天时间,其实在客户面前是毫无价值的。

    第二段代码多么的丑陋,好多问题(我自己认为,当时为了解决问题没有考虑那么多的代码有雅性),但是对于客户来说非常有价值减轻了他们的工足量。

    总结如下:

      (1) 代码量的多少以及编写代码所花费的时间都不是软件的价值

    (2) 写代码最重要的目的是解决实际问题(操作方便,减轻工作,舒适美感)

    (3) 代码对软件的价值是体现软件的便捷性以及强大的功能

    (4) 客户是不会买你代码量的账的,客户不懂代码也不愿意鸟你的代码是如何实现的

    (5) 解决客户问题了你的代码就有价值 

    以上结论不代表说代码规范性不重要,代码规范性是为了实现好的软件,将软件的优势体现出来,代码本身是不具备任何价值的。

 

  二. 服务价值和软件价值

    软件是为客户服务的,这两者有必然的联系! 那软件的价值是不是就是服务的价值呢。

    问题1:客户是买你的软件还是买你的服务

    问题2: 除软件之外的服务,你的价值又体现在哪里

    现在很多公司都很牛气,给某个公司卖了一套软件然后实施成功之后,那后面的技术服务态度就烂的.... ,以前深有体会。他们总会这样回复:" 我们的软件在其他公司都用的很好,就你们的问题特别多,你们现在的问题不属于我们的服务范围 "。当初买软件的时候到底是买的软件还是服务啊,反正现在也说不清了。现在个人认为客户买你的软件是需要你的软件服务他们公司更好的协同工作管理,而所需的服务就是在软件出现问题的时候或者软件不知道怎么使用的时候能够快速提供帮助。所谓服务其实也就是"客户哪里痒你就帮他挠哪里"。

    

    同样一款软件很多公司都可以开发,而且开发的很不错,无论是在操作便捷性还是界面美观性上都很不错,现在这样的公司非常多。但是客户为什么要选择你为他们开发软件,难倒真的是因为你们公司其他公司技术要厉害么(这里排除价格的问题)。

     这里先给各位看看一个界面的截图:

这个是打印一个施工单的部分界面截图,这个页面打印可能稍微有点复杂啊,不过我相信大部分技术公司都能够做出来. 

当时我公司去实施这个项目的时候,并没有提到这个东西,打印一个施工单据随着生产施工去流转。因为在生产车间不能使用电脑,某个产品生产到那个步骤了需要知道。我们提出了一个方案就是将每一次施工的流程打印出来放到车间中去,每到工艺流程结束之后这个施工单会随着产品走动,操作人员可以看到目前进行到哪一步了。

 

这个功能并不是很强大,功能也不是很起眼,但是这个很重要,为什么,因为你帮助他们实际解决了生产车间的问题,生产车间的环境你以为都跟办公室一样啊。别说工人赚的钱比你码农多,他们的的确确是辛苦钱。

 

    在这个问题上,我们除了客户要求的软件功能之外,还帮他们处理一件实际操作中的问题,客户没有想到用这种方式来解决,但是我们想到了并且帮他们实施了,我们的价值体现出来了。我们的价值就是解决客户实际生产中遇到的问题,我们是深入到他们的生产工艺流程中去了,而不只是简单的为他们开发了一套软件然后他们可以用。 很多公司认为我们为客户开发了一套软件这就是我们的价值,这话的确没错,但是你能够做到的其他公司也能够做到,但是都没有解决客户痛痒的根源。

    总结:

    (1) 软件的开发只能体现你的技术能力比较强

    (2) 能够解决客户的痛痒问题那就是你的真正价值,这个部分在软件之内但是绝对的高于软件

    (3) 客户对你的认可肯定不只是你会开发软件

    (4) 服务不只是随叫随到,而是主动去帮助思考问题

 

  三. 个人的价值

    跑了好多工厂,也认识了很多很多工厂车间工作的工人,有时候我们会讨论到工资的问题,估算下来他们的平均工资也就3000-4000左右吧,这算比较不错的了(这里是只流水线上的工人,不是车间里面的技术工,技术工也有很高工资的,甚至比码农还要高)。目前我所了解到的做开发的技术人员工资毕业差不多也有四五千吧,我公司是这样的一个标准。

    工厂流水工工资级别停留在了3000-4000,而技术开发人员这只是一个起步,不同的行业为什么有这么大的差别?

    显而易见的是技术开发人员是脑力工作,而流水工时体力工作,这个社会大的基本形态就是这样的,脑力比体力赚钱多。

    

    下面的观点请各位勿喷:

    1. 外包的为什么总是抱怨自己学不到公司,在我的观点中外包就是码代码的,这属于脑力中的体力活,几乎很少有人会去管这个事情是不是一定要干好,你的价值就是代码量的产出量

    2. 为什么公司总是不给我加薪,或者加薪那么少? 作为程序员你为公司是奉献了脑力还是体力?如果程序员能够很清楚这个我估计加薪也不会少?[之前有给公司提过50%的加薪,公司很爽快答应了,当然也有进步源于起点低的原因]

    3. 我不只是码代码的程序员,很多人都是这么想但是很多人都是这么做的,到公司你就将自己定位了自己是做技术的,什么是做技术那就是写代码。

    4. 如何发挥自己的价值,不是写好代码就可以了,还要让自己写好的代码转化为让客户接受并欣赏,那就是你的价值。

    5. 你做一件事如果你发现今后有让你激动的地方那你就有价值了。

    以前的一个同事给我说,公司那一年只有你们项目做的东西在公司算是真正盈利了的,想当初那是何等的痛苦啊,当时自己都瞧不起那样的项目,可是客户认可产生了价值,你也就有价值了,当时你解决了公司的项目问题并且让其得以持续下去(解决问题不一定只是技术问题)。听到这个热泪盈眶啊,你所有付出的都得到了认可,你是有价值的人。

    

 

本文也是杂七杂八的乱写,貌似现在做了实施事情时间也比较自由多了,关键是还有时间写文章啊,虽然写的不怎么好,希望大家勿喷!

换一种思路换一种角度思考问题可能会让你更加的透彻明白,最近自己的一些工作体会分享给还在办公室角落独自写代码的技术人员,走出来看看或许会让你的目标更加明朗!

 

时间: 2024-10-02 07:37:10

实施项目--你明白软件的价值和个人的价值么?的相关文章

实施项目--为什么开发人员一直在抱怨需求变动

几年前的某个时候,公司大伙都等着下班我却等着晚上加班,因为产品经理对产品的某个功能进行了调整和修改,我必须加班将其修改完善.对于这种事情我已经数不清了,产品经理的每一次变动都得让我们技术部门的同学们加班到深夜甚至到天明,如今回忆起来历历在目!今天这个文章我们不谈论是谁的责任,也不去抨击产品经理的无能,说说技术人员为什么总是在抱怨需求在变动这些事, 希望大家踊跃讨论.   一. 抱怨现象 最近我做了实施人员,经常到各个客户工厂去给他们实施项目,在这个过程中我了解到了软件的真实使用者,在这之间我就成

实施项目--如何推进项目实施进度

周末的时候和一群驴友(22人)到苏州小小自虐了一下,15公里短途穿越,路线规划:灵岩山(走后山)-->大焦山(走非常规线) -->羊肠岭(走小路)-->寿星岭-->白马涧-->花山-->鹿山-->皇冠山.虽说是短途,但还是有点小挑战性的,步行7个半小时左右,回来一身的疲惫,不过很舒坦,非常喜欢这样的运动! 路途中遇到了一位神人,真的是佩服的五体投地,竟然搞了一辆山地自行车上去,差点就要跪地膜拜了. 下面言归正传,说正经事情!   一. 项目实施进度缓慢 在徒步的过

产品是创造了价值还是套现了价值

做产品前,需要先找准产品的定位.这是一句绝对正确的废话.不过我还是想要再写这篇文章,再提醒下自己.因为这个问题,基本上我应该已经算是范了两次了. 一次是在我刚开始做产品设计1年左右的时候,山寨出生,没有人教,一边听老板的高谈阔论,一边疯狂的订阅产品相关blog,体验一个又一个的网站.那个时候,算是刚入门.同时在小公司负责一个新的产品.  那个时候做产品关注更多的是交互效果,关注界面,关注产品功能本身对用户产生的吸引力.那个时候每天不断的去看同类网站,看他们新的模块,新的设计,只要觉得有趣就想搬到

网站的用户价值体现网站的价值

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 对于一个网站来说,它对用户的价值体现出的是网站的价值.没有用户愿意访问的网站收录再高,都是空壳.因为没有核心的产品. 那么如何打造出用户的价值呢? 这个需要从很多方面来说.也就是让用户用的舒服,看的开心.来一次再来两次以致最后的天天来为目标. 需要做的事情很多.各大搜索引擎都倡导改善用户体验,这也就是用户价值! 如何做好用户体验呢? 第一.在

实施项目--.NET实现仓库看板的一些感想

从一名技术开发人员到实施人员的蜕变,从不同的角度看待同一个问题,或许会有不一样的结果.这里记录一下最近一个项目实施的案例,非常有感触! 一. 项目情况简介 本次项目是给一个国外生产型企业做仓库方面的系统,其中有一个功能就是给仓库做一个电子看板.所谓的电子看板就是在一个大屏幕上显示仓库进料和出料的情况,在大屏幕上显示指定数量的单号信息,就和医院的叫号系统一样,每行数据不停的向上滚动. 上面这个功能其实非常简单,就是查询相应的数据在屏幕上显示即可. 仓库每天可能收到20多个订单的进料单据,系统将单据

解读:企业ERP实施项目的评估模型

由于ERP项目涉及的内容十分繁杂,包括观念的转变,机制的转换,业务流程的重组.实施方法.项目管理以及软件(顾问)公司的服务水平等一系列实际问题,使整个项目具有涉及面广.难度大.周期长和系统复杂等特点.同时ERP实施的高失败率一直是业界的共识.但怎样才算ERP实施成功,如何来衡量ERP的实施,目前还没有一个统一的标准.本文将通过比较国内外常见的ERP评估方法,按照ERP实施的生命周期,分5个阶段提出评估ERP实施的方法和相应的指标,并给出了ERP实施的综合评估模型. 1.ERP实施评估发展现状 E

凯迪生态携手海通安恒,成功启动SAP实施项目

2017年4月10日上午,凯迪生态环境科技股份有限公司(以下简称"凯迪生态")信息化项目启动会暨战略合作协议签订仪式在武汉隆重召开,标志着项目的成功启动. 凯迪生态联合创始人唐宏明.董事罗廷元.总裁张海涛出席并发表重要讲话,集团部长级以上干部160多位成员出席本次会议.武汉企业信息化促进会秘书长胡颲.海通安恒总裁王传平.副总裁石孝芳,SAP能源行业首席架构师肖伟莅临现场.会议明确了本次的项目目标是以财务业务一体化为导向,通过SAP平台建设,借力"两化融合"的春风,加

网络营销“拉”的价值高于“推”的价值

中介交易 SEO诊断 淘宝客 云主机 技术大厅 网络营销将是21世纪广泛得以应用的营销方式,网络营销的两大目标:产品销售和品牌服务. 进入2008年,新浪.搜狐.网易意外地退出互联网流量前三名的行列,取而代之的是百度.腾讯和Google.广告主已经意识到,搜索引擎广告并不仅仅只是关键词.竞价排名等形式,也不局限于只服务广大中小企业,更不是只适合促进产品销售.事实上,以搜索引擎为基础的传播产品,在国外已经广泛地被品牌广告主认同.品牌广告主已经认识到,在搜索引擎上投放品牌广告也是非常重要的,而传播的

网站推广:“拉”的价值高于“推”的价值

中介交易 SEO诊断 淘宝客 云主机 技术大厅     网络营销将是21世纪广泛得以应用的营销方式,网络营销的两大目标:产品销售和品牌服务. 进入2008年,新浪.搜狐.网易意外地退出互联网流量前三名的行列,取而代之的是百度.腾讯和Google.广告主已经意识到,搜索引擎广告并不仅仅只是关键词.竞价排名等形式,也不局限于只服务广大中小企业,更不是只适合促进产品销售.事实上,以搜索引擎为基础的传播产品,在国外已经广泛地被品牌广告主认同.品牌广告主已经认识到,在搜索引擎上投放品牌广告也是非常重要的,