为防被程序员「砍」,产品经理需要注意这些场景

为防被程序员「砍」,产品经理需要注意这些场景,第1张

互联网行业中,众人热衷于讨论「程序员产品经理」。虽然,「砍」更多是调侃的意思,一种消遣工作的方式;但是,这不是一个饭后笑话,侧面反应了产品经理和程序员间的对立关系。很多时候,产品经理和程序员间就像对手,产品研发过程就像打仗,总要争个你死我亡。「砍」的本质,是程序员表达对产品经理的不满,也是一种情绪的宣泄。

在产品研发的过程中,产品经理与程序员对立关系,会严重影响项目的推进。一旦产品经理和程序员对立关系公开化,很容易导致团队人心涣散。这种对立关系,经常滋生出一些极端的事情,骂娘、打架已屡见不鲜。

下文就列举一些程序员想砍产品经理的场景。这些场景都是我过去和很多程序员朋友交流时,他们遇到的对产品不满的场景。这些场景,都会以产品经理的沟通话语表现出来。通过这些场景,去解析这种对立关系产生的原因。以及,作为对照,产品经理应该如何规避和处理这种对立关系。

这样说法是程序员们最不喜欢的,最容易惹毛程序员的。这句话,在程序员们看来就是削减工时、加班的代名词,他们当然不喜欢。而且他们也非常讨厌,一个非技术人员为技术人员做技术难度的定论。简不简单,都需要技术人员做了技术评估,才能下结论。

这种言语,会让程序员们觉得产品经理不靠谱。大家通常都是比较排斥借鉴。借鉴你也得有合理明确的理由。以我某程序员朋友的话来说:微信怎么做的,你就怎么做,那你不如去微信做产品算了。

每个产品,在表面的UI下,都有其背后的复杂的业务逻辑。如果产品经理只是叫程序员照着某个产品做,很多时候技术们是很难实现的,因为他们也需要弄懂背后的逻辑和流程。当然,这应该是产品经理的工作。

这就是抬杠。产品经理虽然名字里面有「经理」二字,但并没有经理的权利,当然不能命令合作的技术们。这句话,言下之意也是拒绝了商量和讨论。而程序员也需要参与感和团队感。

这就是质疑他人能力,是人都不会喜欢。如果产品经理提出的方案,程序员们没有理解。那就说明产品经理的解释说明和文档,做的不够优秀,不够简洁易懂。让程序员们理解需求,是产品经理的基本工作内容。

在互联网产品开发中,修改需求和插入新需求都是挺常见的。对于程序员们来说,这是非常不爽的事情。这种 *** 作通常会打断程序员的思路,思路被打断是非常痛苦的。当然,这样也会影响他们的开发效率。更可怕的是,反复的修改需求,会使他们有种劳动成果不被尊重的感受,同时也会对项目的未来抱有怀疑的态度。反复的更改方案,也说明产品经理设计是未经过严密的论证,或对细节的把控是不够。

程序员都比较讨厌反复的催促。当项目的节点确定后,技术们会严格遵守节点,产品应该信任他们。当然,时间比较紧凑时,反复催促也会加大程序员们的压力,使他们变得非常烦躁。在这种时候,催促就是添麻烦。

甩锅会导致团队分崩离析,人心不齐。不管任何问题,都是团队的责任,不要将责任指定给某人。特别是在项目复盘时,如果心态不好同事,这是非常难堪的。所以,我们要尽量以原因和结果为导向,而不是责任为导向。

程序员也是也是团队的一份子,有权利知道知道需求的背景。同时,了解需求背景也利于程序员们更好的开发程序。

产品经理给程序员们画饼是最不切实际的,只会引起大家的反感。程序员都是喜欢偏实际的东西,虚的东西只会招致白眼。

任何传递给程序员的需求,都是需要有计划和规范的。如果口头传达一个需求,很容易导致开发出的功能与需求不匹配。同时,因为缺乏相关的记录和文档,可能会造成需求流失。这对于程序员们来说,可能就是延迟、加班、返工、担责等等风险。这是团队合作的大忌,也是项目管理不专业的体现。

以上的这些场景,可能出现一次,程序员们都会顺着我们的想法做。但是,这会渐渐改变程序员们的心态,最终会使产品经理与程序员间产生隔阂和矛盾。如果出现这些场景,作为产品经理都需要小心的处理好,以免影响项目的正常推进。当然,最好是不要出现这些场景。作为产品经理,我们的最终目标,都是要保证我们的产品,准时、保质、保量的落地。

产品经理在与程序员们合作时,产品经理需要讲究合作共赢、互相体谅。在产品经理的相关工作中,最要避免的就是抬杠。抬杠是一切矛盾的根源。很多时候,产品经理要站在程序员的角度考虑问题。比如,对于产品来说可能就是改改需求,但对于程序员,他们更在意的可能是因为改需求而导致的加班。

产品经理在工作中,经常会追求产品上的极致。追求极致本身是好事,但是切忌过分偏执。我们也需要考虑团队的现状和资源,在极致和现实间寻找均衡。毕竟,如果没有乔布斯的团队,要像乔布斯一样做产品,只会拖垮团队。

在产品开发的过程,改需求、改方案等项目异常,都是不可避免的。这是项目管理的第一部分。如何进行项目异常的处理,考验的是产品经理的沟通能力和项目管理能力。产品经理需要在保持技术们高效工作的情况下,完成项目异常的处理。

当然,在产品经理工作中,矛盾的根源也并不总是产品经理。有时候,也可能是某些程序员的性格或者对该工作的态度导致的。这时候,产品经理要明确,作为团队的润滑剂,有责任推动和协调大家的工作。如果,矛盾不可调和,我们需要尽早提出问题、控制风险,避免「勉强」行事。

有时候,程序员在私下评价一起工作的产品经理时,总是会补加一句「我感觉我也能做产品经理」。这句话的背后,是产品经理没有让程序员们感受到产品工作的价值。在这种背景下,产品经理是很难获取程序员们的注重,也会为很多争论埋下诱因。那如何感受到我们工作的价值那?其实很简单,就是保持工作信息的透明。将我们针对需求和产品做的相关工作,体现在我们的沟通或者文档中。

导致程序员想「砍」产品经理,本质是产品经理工作方式的问题,也有情商的问题。在我的产品经理工作经验中,我总结下了以下四点,我们需要注意和避免的。这四点,都可以和上文的场景相对应,是最容易慢慢改变程序员的心态的。

Java从诞生以来,其基因就是开放精神,也正因此,其可以得到广泛爱好者的支持和奉献,最终很快发展壮大,以至于有今天之风光!但随着java的应用领域越来越广,特别是一些功能要发布到终端用户手中(如Android开发的app),有时候,公司为了商业技术的保密考虑,不希望这里面的一些核心代码能够被人破解(破解之后,甚至可以被简单改改就发布出去,说严重点,就可能会扰乱公司的正常软件的市场行为),这时候就要求这些java代码不能够被反编译。

这里要先说一下反编译的现象。因为java一直秉持着开放共享的理念,所以大家也都知道,我们一般共享一个自己写的jar包时,同时会共享一个对应的source包。但这些依然与反编译没有什么关系,但java的共享理念,不只是建议我们这样做,而且它自己也在底层上“强迫”我们这么做!在java写的.java文件后,使用javac编译成class文件,在编译的过程,不像C/C++或C#那样编译时进行加密或混淆,它是直接对其进行符号化、标记化的编译处理,于是,也产生了一个逆向工程的问题:可以根据class文件反向解析成原来的java文件!这就是反编译的由来。

但很多时候,有些公司出于如上述的原因考虑时,真的不希望自己写的代码被别人反编译,尤其是那些收费的app或桌面软件(甚至还有一些j2ee的wen项目)!这时候,防止反编译就成了必然!但前面也说过了,因为开放理念的原因,class是可以被反编译的,那现在有这样的需求之后,有哪些方式可以做到防止反编译呢?经过研究java源代码并进行了一些技术实现(结果发现,以前都有人想到过,所以在对应章节的时候,我会贴出一些写得比较细的文章,而我就简单阐述一下,也算偷个懒吧),我总共整理出以下这几种方式:

代码混淆

这种方式的做法正如其名,是把代码打乱,并掺入一些随机或特殊的字符,让代码的可读性大大降低,“曲线救国”似的达到所谓的加密。其实,其本质就是打乱代码的顺序、将各类符号(如类名、方法名、属性名)进行随机或乱命名,使其无意义,让人读代码时很累,进而让人乍一看,以为这些代码是加过密的!

由其实现方式上可知,其实现原理只是扰乱正常的代码可读性,并不是真正的加密,如果一个人的耐心很好,依然可以理出整个程序在做什么,更何况,一个应用中,其核心代码才是人们想去了解的,所以大大缩小了代码阅读的范围!

当然,这种方式的存在,而且还比较流行,其原因在于,基本能防范一些技术人员进行反编译(比如说我,让我破解一个混淆的代码,我宁愿自己重写一个了)!而且其实现较为简单,对项目的代码又无开发上的侵入性。目前业界也有较多这类工具,有商用的,也有免费的,目前比较流行的免费的是:proguard(我现象临时用的就是这个)。

上面说了,这种方式其实并不是真正加密代码,其实代码还是能够被人反编译(有人可能说,使用proguard中的optimize选项,可以从字节流层面更改代码,甚至可以让JD这些反编译软件可以无法得到内容。说得有点道理,但有两个问题:1、使用optimize对JDK及环境要求较高,容易造成混淆后的代码无法正常运行;2、这种方式其实还是混淆,JD反编译有点问题,可以有更强悍的工具,矛盾哲学在哪儿都是存在的^_^)。那如何能做到我的class代码无法被人反编译呢?那就需要我们下面的“加密class”!

加密class

在说加密class之前,我们要先了解一些java的基本概念,如:ClassLoader。做java的人已经或者以后会知道,java程序的运行,是类中的逻辑在JVM中运行,而类又是怎么加载到JVM中的呢(JVM内幕之类的,不在本文中阐述,所以点到为止)?答案是:ClassLoader。JVM在启动时是如何初始化整个环境的,有哪些ClassLoader及作用是什么,大家可以自己问度娘,也不在本文中讨论。

让我们从最常见的代码开始,揭开一下ClassLoader的一点点面纱!看下面的代码:

Java代码

public class Demo{

public static void main(String[] args){

System.out.println(“hello world!”)

}

}

上面这段代码,大家都认识。但我要问的是:如果我们使用javac对其进行编译,然后使用java使其运行(为什么不在Eclipse中使用Run as功能呢?因为Eclipse帮我们封闭,从而简化了太多东西,使我们忽略了太多的底层细节,只有从原始的 *** 作上,我们才能看到本质),那么,它是怎么加载到JVM中的?答案是:通过AppClassLoader加载的(相关知识点可以参考:http://hxraid.iteye.com/blog/747625)!如果不相信的话,可以输出一下System.out.println(Thread.currentThrea().getContextLoader())看看。

那又有一个新的问题产生了:ClassLoader又是怎样加载class的呢?其实,AppClassLoader继承自java.lang.ClassLoader类,所以,基本 *** 作都在这个类里面,让我们直接看下面这段核心代码吧:

看看这个方法中的逻辑,非常简单,先从内存中找,如果没有,则从父级或根先找,如果没找到,则再从自己的方法里面找!那findClass里面是什么样的呢?很不幸,这个方法是个抽象(abstract)的,也就是使用什么方式加载,由程序使用ClassLoader自己决定!这就给我们留下了巨大的“”!让我们看一下非常常见的一个ClassLoader的实现,那就是URLClassLoader(几乎所有的j2ee的web项目的容器使用的ClassLoader都是继承自它),让我们看一下它的findClass的实现:

这个方法里面的逻辑也很简单,从定义的ucp(就是各个jar包或class文件的具体路径)中读取指定的class文件的信息(如字节流之类),然后交给defineClass定义到JVM中,让我们继续看一下这个方法的核心部分:

看到这里,已经没有必要再往下面看了(再往下就是native方法了,这是一个重大伏笔哦),我们要做的手脚就在这里!

手脚怎么做呢?很简单,上面的代码逻辑告诉我们,ClassLoader只是拿到class文件中的内容byte[],然后交给JVM初始化!于是我们的逻辑就简单了:只要在交给JVM时是正确的class文件就行了,在这之前是什么样子无所谓!所以,我们的加密的整个逻辑就是:

在编译代码时(如使用ant或maven),使用插件将代码进行加密(加密方式自己选),将class文件里面的内容读取成byte[],然后进行加密后再写回到class文件(这时候class文件里面的内容不是标准的class,无法被反编译了)

在启动项目代码时,指定使用我们自定义的ClassLoader就行了,而自定义的部分,主要就是在这里做解密工作!

如此,搞定!以上的做法比较完整的阐述,可以仔细阅读一下这篇文章:https://www.ddtsoft.com/#developerworks/cn/java/l-secureclass/文章中的介绍。

通过这个方法貌似可以解决代码反编译的问题了!错!这里有一个巨大的坑!因为我们自定义的ClassLoader是不能加密的,要不然JVM不认识,就全歇菜了!如果我来反编译,呵呵,我只要反编译一下这个自定义的ClassLoader,然后把里面解密后的内容写到指定的文件中保存下来,再把这个加了逻辑的自定义ClassLoader放回去运行,你猜结果会怎样?没错,你会想死!因为你好不容易想出来的加密算法,结果人家根本不需要破解,直接就绕过去了!

现在,让我们总结一下这个方法的优缺点:实现方式简单有效,同时对代码几乎没有侵入性,不影响正常开发与发布。缺点也很明显,就是很容易被人破解!

当然啦,关于缺点问题,你也可以这么干:先对所有代码进行混淆、再进行加密,保证:1、不容易找到我们自定义的那个ClassLoader;2、就算找到了,破解了,代码可读性还是很差,让你看得吐血!(有一篇文章,我觉得写得不错,大家可以看一看:http://www.scjgcj.com/#blog/851544)

嗯,我觉得这个方法很好,我自己也差点被这个想法感动了,但是,作为一个严谨的程序员,我真的不愿意留下一个隐患在这里!所以,我继续思索!

高级加密class

前面我们说过有个伏笔来着,还记得吧?没错,就是那个native!native定义的方法是什么方法?就是我们传说中的JNI调用!前面介绍过的有一篇文章中提到过,其实jvm的真实身份并不是java,而是c++写的jvm.dll(windows版本下),java与dll文件的调用就是通过JNI实现的!于是,我们就可以这样想:JNI可以调用第三方语言的类库,那么,我们可不可以把解密与装载使用第三方语言写(如C++,因为它们生成的库是不好反编译的),这样它可以把解密出来的class内容直接调jvm.dll的加载接口进行初始化成class,再返回给我们的ClassLoader?这样,我们自定义的ClassLoader只要使用JNI调用这个第三方语言写的组件,整个解密过程,都在黑盒中进行,别人就无从破解了!

嗯,这个方法真的很不错的!但也有两个小问题:1.使用第三方语言写,得会第三方语言,我说的会,是指很溜!2.对于不同的 *** 作系统,甚至同一 *** 作系统不同的版本,都可能要有差异化的代码生成对应环境下的组件(如window下是exe,linux是so等)!如果你不在乎这两个问题,我觉得,这个方式真的挺不错的。但对于我来说,我的信条是,越复杂的方式越容易出错!我个人比较崇尚简洁的美,所以,这个方法我不会轻易使用!

对了,如果大家觉得这个方法还算可行的话,可以推荐一个我无意中看到的东西给大家看看(我都没有用过的):jinstall,

更改JVM

看到这个标题,我想你可能会震惊。是的,你没看错,做为一个程序员,是应该要具有怀疑一切、敢想敢做的信念。如果你有意留心的话,你会发现JVM版本在业界其实也有好几个版本的,如:Sun公司的、IBM的、Apache的、Google的……

所以,不要阻碍自己的想象力,现在没有这个能力,并不代表不可能。所以,我想到,如果我把jvm改了,在里面对加载的类进行解密,那不就可以了吗?我在设计构思过程中,突然发现:人老了就是容易糊涂!前面使用第三方语言实现解密的两个问题,正好也是更改JVM要面对的两个问题,而且还有一个更大的问题:这个JVM就得跟着这个项目到处走啊!

那么程序员为什么秃呢?

1、大量的脑力活动

在脑力劳动中,大脑需要消耗大量的氧气和能源,对皮肤、毛发这类的血液供给就会减弱,导致头发生长周期不稳定;而且脑力劳动还会促进雄激素的分泌,程序员大脑长期处于紧张、高度注意力集中的状态时,需要雄激素来维持这样的状态,而雄激素升高对于脱发有很大的影响。

2、熬夜和不规律作息

头发的生长是和激素调节非常密切的一件事情,而熬夜和不规律的作息最容易破坏内分泌的平衡,短期内导致脱发,长期下来则会出现更大的健康隐患。

3、精神压力大

一个风光项目的背后,是很多程序员夜以继日的反复修改。程序员经常面临着项目验收、客户修改需求和反馈BUG等问题,可以说精神压力非常大。人在精神压力的环境下,内分泌系统和免疫系统都可能受到一定程度的调节障碍,引发一些暂时性的机体反馈,比如斑秃,失眠,多梦,头痛等等问题。

4、饮食不规律

人体的能量代谢需要大量的维生素B族,血液输氧则需要充足的铁元素,一般程序员最缺乏这两类东西。吃饭不讲究的程序员经常吃泡面、快餐等食物,还容易缺乏蛋白质,更是雪上加霜!

推荐使用乐喜力丝育发液,可以改善毛囊环境,来进行防脱生发哦!


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7734327.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-09
下一篇 2023-04-09

发表评论

登录后才能评论

评论列表(0条)

保存