SQL注入

SQL注入 维基百科

PreparedStatement

Secure Usage

PreparedStatement stmt = connection.prepareStatement("SELECT * FROM users WHERE userid=? AND password=?");
stmt.setString(1, userid);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();

Vulnerable Usage

// Example #1
String query = "SELECT * FROM users WHERE userid ='"+ userid + "'" + " AND password='" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
// Example #2
String query = "SELECT * FROM users WHERE userid ='"+ userid + "'" + " AND password='" + password + "'";
PreparedStatement stmt = connection.prepareStatement(query);
ResultSet rs = stmt.executeQuery();

Hibernate

Secure Usage

/* Positional parameter in HQL */
Query hqlQuery = session.createQuery("from Orders as orders where orders.id = ?");
List results = hqlQuery.setString(0, "123-ADB-567-QTWYTFDL").list();

/* named parameter in HQL */
Query hqlQuery = session.createQuery("from Employees as emp where emp.incentive > :incentive");
List results = hqlQuery.setLong("incentive", new Long(10000)).list();

/* named parameter list in HQL */
List items = new ArrayList(); 
items.add("book"); items.add("clock"); items.add("ink");
List results = session.createQuery("from Cart as cart where cart.item in (:itemList)").setParameterList("itemList", items).list();

/* JavaBean in HQL */
Query hqlQuery = session.createQuery("from Books as books where book.name = :name and book.author = :author");
List results = hqlQuery.setProperties(javaBean).list(); //assumes javaBean has getName() & getAuthor() methods.

/* Native-SQL */
Query sqlQuery = session.createSQLQuery("Select * from Books where author = ?");
List results = sqlQuery.setString(0, "Charles Dickens").list();

Vulnerable Usage

List results = session.createQuery("from Orders as orders where orders.id = " + currentOrder.getId()).list();
List results = session.createSQLQuery("Select * from Books where author = " + book.getAuthor()).list();

JPA

Secure Usage

/* positional parameter in JPQL */
Query jpqlQuery = entityManager.createQuery("Select order from Orders order where order.id = ?1");
List results = jpqlQuery.setParameter(1, "123-ADB-567-QTWYTFDL").getResultList();

/* named parameter in JPQL */
Query jpqlQuery = entityManager.createQuery("Select emp from Employees emp where emp.incentive > :incentive");
List results = jpqlQuery.setParameter("incentive", new Long(10000)).getResultList();

/* named query in JPQL - Query named "myCart" being "Select c from Cart c where c.itemId = :itemId" */
Query jpqlQuery = entityManager.createNamedQuery("myCart");
List results = jpqlQuery.setParameter("itemId", "item-id-0001").getResultList();

/* Native SQL */
Query sqlQuery = entityManager.createNativeQuery("Select * from Books where author = ?", Book.class);
List results = sqlQuery.setParameter(1, "Charles Dickens").getResultList();

Vulnerable Usage

List results = entityManager.createQuery("Select order from Orders order where order.id = " + orderId).getResultList();
List results = entityManager.createNativeQuery("Select * from Books where author = " + author).getResultList();
int resultCode = entityManager.createNativeQuery("Delete from Cart where itemId = " + itemId).executeUpdate();

MyBatis

Secure Usage

<select id="getPerson" parameterType="int" resultType="org.application.vo.Person">
SELECT * FROM PERSON WHERE ID = #{id}
</select>

/* Comparable JDBC code */
String selectPerson = "SELECT * FROM PERSON WHERE ID = ?"; 
PreparedStatement ps = conn.prepareStatement(selectPerson); 
ps.setInt(1, id);

<insert id="insertPerson" parameterType="org.application.vo.Person">
insert into Person (id, name, email, phone)
values (#{id}, #{name}, #{email}, #{phone})
</insert>
 
<update id="updatePerson" parameterType="org.application.vo.Person">
update Person set name = #{name}, email = #{email}, phone = #{phone}
where id = #{id}
</update>
 
 
<delete id="deletePerson" parameterType="int">
delete from Person where id = #{id}
</delete>

Vulnerable Usage

<select id="getPerson" parameterType="string" resultType="org.application.vo.Person">
SELECT * FROM PERSON WHERE NAME = #{name} AND PHONE LIKE '${phone}'; 
</select>

<insert id="insertPerson" parameterType="org.application.vo.Person">
insert into Person (id, name, email, phone)
values (#{id}, #{name}, #{email}, ${phone})
</insert>
 
<update id="updatePerson" parameterType="org.application.vo.Person">
update Person set phone = ${phone}
where id = #{id}
</update>
 
 
<delete id="deletePerson" parameterType="int">
delete from Person where id = ${id}
</delete>

Java Ring Buffer

Ring Buffer 是一个固定容量大小的数组。维护两个下标,一个写入,一个读取。
类似一个环,怎么计算写入和读取的下标,有2种方式实现:
1.记录当前的已经写入的数量
2.记录一个反转标记

//记录写入数量,实现RingBuffer
public class RingBufferFillCount {

    public Object[] elements = null;
    private int capacity = 0;
    private int writePos = 0;
    private int available = 0;

    public RingBufferFillCount(int capacity) {
        this.capacity = capacity;
        this.elements = new Object[capacity];
    }

    public void reset() {
        this.writePos = 0;
        this.available = 0;
    }

    public int getCapacity() {
        return capacity;
    }

    public int getAvailable() {
        return available;
    }

    public int remainingCapacity() {
        return this.capacity - this.available;
    }

    public boolean put(Object element) {
        if (available < capacity) {
            if (writePos >= capacity) {
                writePos = 0;
            }
            elements[writePos] = element;
            writePos++;
            available++;
            return true;
        }
        return false;
    }

    public Object take() {
        if (available == 0) {
            return null;
        }
        int nextSlot = writePos - available;
        if (nextSlot < 0) {
            nextSlot += capacity;
        }
        Object nextObj = elements[nextSlot];
        available--;
        return nextObj;
    }

    public int put(Object[] newElements) {
        return put(newElements, newElements.length);
    }

    public int put(Object[] newElements, int length) {
        int readPos = 0;
        if (this.writePos > this.available) {
            //直接追加
            if (length <= this.capacity - this.writePos) {
                for (; readPos < length; readPos++) {
                    this.elements[this.writePos++] = newElements[readPos];
                }
                this.available += readPos;
                return length;
            } else {
                //需要在数组尾部和头部添加
                for (; this.writePos < this.capacity; this.writePos++) {
                    this.elements[this.writePos] = newElements[readPos++];
                }
                //重置写入下标
                this.writePos = 0;
                //计算还能写入多少
                int endPos = Math.min(length - readPos, capacity - available - readPos);
                for (; this.writePos < endPos; this.writePos++) {
                    this.elements[this.writePos] = newElements[readPos++];
                }
                this.available += readPos;
                return readPos;
            }
        } else {
            int endPos = this.capacity - this.available + this.writePos;
            for (; this.writePos < endPos; this.writePos++) {
                this.elements[this.writePos] = newElements[readPos++];
            }
            this.available += readPos;
            return readPos;
        }
    }

    public int take(Object[] into) {
        return take(into, into.length);
    }


    public int take(Object[] into, int length) {
        int intoPos = 0;

        if (available <= writePos) {
            int nextPos = writePos - available;
            int endPos = nextPos + Math.min(available, length);
            for (; nextPos < endPos; nextPos++) {
                into[intoPos++] = this.elements[nextPos];
            }
            this.available -= intoPos;
            return intoPos;
        } else {
            int nextPos = writePos - available + capacity;
            int leftInTop = capacity - nextPos;
            if (length <= leftInTop) {
                //copy directly
                for (; intoPos < length; intoPos++) {
                    into[intoPos] = this.elements[nextPos++];
                }
                this.available -= length;
                return length;
            } else {
                //copy top
                for (; nextPos < capacity; nextPos++) {
                    into[intoPos++] = this.elements[nextPos];
                }
                //copy bottom - from 0 to writePos
                nextPos = 0;
                int leftToCopy = length - intoPos;
                int endPos = Math.min(writePos, leftToCopy);
                for (; nextPos < endPos; nextPos++) {
                    into[intoPos++] = this.elements[nextPos];
                }
                this.available -= intoPos;
                return intoPos;
            }
        }
    }
}
//使用反转标记,实现RingBuffer
public class RingBufferFlipMarker {

    public Object[] elements = null;

    public int capacity = 0;
    public int writePos = 0;
    public int readPos = 0;
    public boolean flipped = false;

    public RingBufferFlipMarker(int capacity) {
        this.capacity = capacity;
        this.elements = new Object[capacity];
    }

    public void reset() {
        this.writePos = 0;
        this.readPos = 0;
        this.flipped = false;
    }

    public int remainingCapacity() {
        if (!flipped) {
            return capacity - writePos;
        }
        return readPos - writePos;
    }

    public int available() {
        if (!flipped) {
            return writePos - readPos;
        }
        return capacity - (writePos - readPos);
    }

    public boolean put(Object element) {
        if (!flipped) {
            if (writePos == capacity) {
                writePos = 0;
                flipped = true;
                if (writePos < readPos) {
                    elements[writePos++] = element;
                    return true;
                } else {
                    return false;
                }
            } else {
                elements[writePos++] = element;
                return true;
            }
        } else {
            if (writePos < readPos) {
                elements[writePos++] = element;
                return true;
            } else {
                return false;
            }
        }
    }

    public Object take() {
        if (!flipped) {
            if (readPos < writePos) {
                return elements[readPos++];
            } else {
                return null;
            }
        } else {
            if (readPos == capacity) {
                readPos = 0;
                flipped = false;
                if (readPos < writePos) {
                    return elements[readPos++];
                } else {
                    return null;
                }
            } else {
                return elements[readPos++];
            }
        }
    }

    public int put(Object[] newElements, int length) {
        int newElementsReadPos = 0;
        if (!flipped) {
            //readPos lower than writePos - free sections are:
            //1) from writePos to capacity
            //2) from 0 to readPos
            if (length <= capacity - writePos) {
                //new elements fit into top of elements array - copy directly
                for (; newElementsReadPos < length; newElementsReadPos++) {
                    this.elements[this.writePos++] = newElements[newElementsReadPos];
                }
                return newElementsReadPos;
            } else {
                //new elements must be divided between top and bottom of elements array
                //writing to top
                for (; this.writePos < capacity; this.writePos++) {
                    this.elements[this.writePos] = newElements[newElementsReadPos++];
                }
                //writing to bottom
                this.writePos = 0;
                this.flipped = true;
                int endPos = Math.min(this.readPos, length - newElementsReadPos);
                for (; this.writePos < endPos; this.writePos++) {
                    this.elements[writePos] = newElements[newElementsReadPos++];
                }
                return newElementsReadPos;
            }
        } else {
            //readPos higher than writePos - free sections are:
            //1) from writePos to readPos
            int endPos = Math.min(this.readPos, this.writePos + length);
            for (; this.writePos < endPos; this.writePos++) {
                this.elements[this.writePos] = newElements[newElementsReadPos++];
            }
            return newElementsReadPos;
        }
    }

    public int take(Object[] into, int length) {
        int intoWritePos = 0;
        if (!flipped) {
            //writePos higher than readPos - available section is writePos - readPos
            int endPos = Math.min(this.writePos, this.readPos + length);
            for (; this.readPos < endPos; this.readPos++) {
                into[intoWritePos++] = this.elements[this.readPos];
            }
            return intoWritePos;
        } else {
            //readPos higher than writePos - available sections are
            //top + bottom of elements array
            if (length <= capacity - readPos) {
                //length is lower than the elements available at the top
                //of the elements array - copy directly
                for (; intoWritePos < length; intoWritePos++) {
                    into[intoWritePos] = this.elements[this.readPos++];
                }
                return intoWritePos;
            } else {
                //length is higher than elements available at the top of the elements array
                //split copy into a copy from both top and bottom of elements array.
                //copy from top
                for (; this.readPos < capacity; this.readPos++) {
                    into[intoWritePos++] = this.elements[this.readPos];
                }
                //copy from bottom
                this.readPos = 0;
                this.flipped = false;
                int endPos = Math.min(this.writePos, length - intoWritePos);
                for (; this.readPos < endPos; this.readPos++) {
                    into[intoWritePos++] = this.elements[this.readPos];
                }
                return intoWritePos;
            }
        }
    }
}

数据分析 – 数据化汇报

场景:
1. 展示:数据分析结果可视化
2. 汇报:用数据向上级汇报工作成果
3. 说服:用数据高效说服别人

展示:
1.比较类图表:柱形图,条形图 描述数据对比关系
2.组合类图表:扇形图,饼图 描述数据的占比
3.描述类图表:散点图,气泡图 呈现数据分布情况

汇报:
向领导展示成绩 这件事情存在一些误区:
1.觉得领导什么都知道,其实他很难知道,管理者花一半的时间花在管理上面,这一半里面,一般有一多半在跟他的上级以及跨部门的沟通,所以他花在自己团队时间只有1/4,这些时间需要平均到6-8个下属,到个人只有3%,所以领导不知道你在干什么,需要跟他说,千里马常有而伯乐不常有,只是千里马不出众。
2.把苦劳当功劳,只说做了什么事,没有量化结果,价值不能量化,公司就不能给你定价,找到你的工作,与公司量化目标的关联。
公司的量化目标有哪些?无非就4类:
1.财务目标
流水,收入,利润,成本,现金流
2.客户目标
客户量,满意度,活跃度,转化率,复购率,品牌知名度,等等
3.运营目标
与公司价值链各项流程相关,比如研发周期,库存周转率,等等
4.组织目标
关键人才流失率,人才敬业度,人才匹配度

说服:

先看一个案例

公司销售经理,发现这个月市场投放过来的用户,很多不是目标用户,希望市场部同事能够调整渠道,以便获取更加精准的用户,来提升销售业绩,下面2种沟通方式:

第一种:

“这个月我们的销售目标没有完成,销售转化率下降了20%,接通率和愿意再聊的客户,平均下降了25%,我们发现市场部获取的目标用户不是很匹配,希望市场部同事能够调整策略,找到更匹配的客户渠道”

第二种:

“今年公司的整体销售目标,月度环比要增长10%,但是我们这个月的目标没有完成,做了全面分析之后,我们发现,虽然市场部提供的销售线索增加了10%,但是销售转化率却下降了20%,从过程指标来看,接通率和愿意再沟通的客户比例,平均下降了25%,这导致我们的销售在没有意向的客户上花费时间。我们需要更精准的目标客户,所以希望和市场团队就用户画像讨论一下,优化渠道策略”

第二种表达,多了一些故事起伏,不是单纯的列数据。

当我们在说服他人的时候,我们需要故事性表达,才能让对方集中注意以及产生认同,这里有一个常用的故事性表达结构:SCQA

SCQA 是四个英文单词缩写:

S是Situation 背景,也就是事情发生的背景信息是什么
C是Complication 复杂性,也就是实际情况和理想情况的差距是什么
Q是Question 问题,也就是当务之急需要解决什么问题
A是Answer 答案,我提出的解决方案是什么

在SCQA的每个要素之下,都有一个观点,把你数据分析的结果,数据可视化图表呈现在这个观点下面,去支持你的观点。

总结:

1)完全一致的数据,改变展现方式,就会改变和扭转一个人对数据的解读和判断

2)工作中常用三种图表

3)通过把自己工作和公司目标关联,量化自己的工作,才能让老板认识到你的价值

4)公司目标可以从这4个方面来找:财务目标,客户目标,运营目标,组织目标

5)与同事沟通时,通过SCQA 故事框架,用数据来佐证框架中的每个观点,就能更有说服力

6)学会使用SCQA来表达

数据分析 – 相关分析法

数据分析 – 相关分析法

目前我们已经知道了,在工作中,我们可以用对比分析来发现并定位问题;用拆解分析,将复杂问题简单化,帮我们找到小的切入点。

但是这样就会存在,同一个问题,我们有时候会找到很多小的切入点。

这个时候需要相关分析,来使用数据判断这些因素是否和最终结果相关,以及相关密切程度高低,据此判断工作优先级。

相关的定义?什么是相关?

相关,就是指两个变量,当一个变量发生变化的时候,另一个变量也跟着变化。比如:工资随着工作年限发生变化,销售量随着价格发生变化,体重随着身高发生变化,等等。

相关分析定义?什么是相关分析?

相关分析,就是去找到两种变量之间的关系。也就是B是怎么随着A的变化产生变化的。

怎么使用相关分析? 相关分析的三大场景:

1、快速锁定大问题相关的一个个小因素,

案例:一位TED演讲嘉宾,她想知道线上交友网站上,怎么设置自己信息才能最好的呈现自己,让自己在社交网站上非常受欢迎。于是,她收集了大量女性账户的行为数据,包含幽默感,语调,声音,沟通方式,个人描述的平均长度,与男性发私信之间隔多久等等。 然后,把这些数据和对应女性受欢迎的程度进行相关分析。发现:最受欢迎的女性都在用诸如“有趣”,“女孩“,”爱“ 这样的关键词,自我介绍一般97个词,以及她们会等23个小时进行下一次沟通。掌握这些信息之后,她建立了一个超级档案,还是本人真实信息,按照分析结果,重新包装,结果她成了网站最受欢迎的人。而且在众多男性里面发现了潜在的”白马王子“,三年之后他们结婚了。

2、用数据说服他人,终结撕逼

除了给自己的工作进行问题分析与定位之外,相关分析可以用在沟通方面,比如:当你在和领导汇报的时候,常常就一件事情进行原因阐述和分析,这个时候每个人都有自己经验和主见,很难达成一致结果,这时候使用相关分析进行验证,就很容易有说服力。

案例:市场部负责投放市场预算在一些渠道,来拉目标用户,而销售负责把产品卖给用户。这个时候,市场和销售会经常撕逼,销售会说:因为市场渠道质量不行,导致销售业绩差,市场会说:销售能力不行,我的渠道质量杠杠的。这个时候就需要采用相关分析,对渠道和销售业绩做一个相关分析,用数据说话,很有说服力。

3、帮我们判断事情优先级

比如,影响销量有非常多的因素,要提升销量,应该做那个?我们就看相关度最高的,因为相关分析得出一个相关系数,根据分值高低判断相关程度,这样就能确定最相关因素,来优先改进和提升。

那么相关分析怎么用了?相关都有哪些类型?

相关可以分为:线性相关,非线性相关

线性相关: y = ax + b , 相关程度就是求斜率。
可以使用Excel或者Python 画出散点图,

相关度R定义: (求出斜率之后 计算数据的拟合度)
1.绝对值大小: 表示相关程度
2.正负:表示正相关还是负相关
3.数值范围:-1 ~ 1
4.数值定义:-1表示负相关,1表示相关,0表示非线性相关(可能其他形式相关)

相关度经验值:
1.绝对值 R >= 0.6 高度相关
2.绝对值 0.3 =< R < 0.6 中度相关
3.绝对值 R < 0.3 弱相关

经典案例:
谷歌收集了美国从2003 到 2008 年期间,流感传播时间和地点,匹配当地,当时人们使用谷歌搜索关键词,寻找其中关系。成功预测了2009冬季流感的传播趋势,甚至可以精确预测流感发生的地区。 根据搜索词语和流感传播关系,建立数据模型,能够提前2周预测大规模流感传播,让人们提前预防。

Facebook,People You May Know, 好友推荐,“你可能认识的人”,这个习以为常的功能,是facebook提升用户留存,进行相关分析,发现有更多的好友,用户粘性越高,越活跃。

相关分析应用范围很广,但是不能滥用,比如我们分析孩子长高的原因不能联想到院子里面的树也长高了。二者虽然都长高了,但是二者并没有相关。

总结:

1)分析问题本质就是对大问题拆解
2)相关分析,去找到2个变量之间的关系
3)相关分析三个场景:1.锁定大问题相关因素 2.数据说服,停止撕逼 3.判断事情优先级
4)了解应用场景,知行合一才能完美解决问题
5)相关分为:线性和非线性
6)相关分析可以做预测
7)因果关系才是相关分析的目标

数据分析-漏斗分析法

漏斗分析法:对问题进行拆解,将复杂问题简单化

分析问题的本质,其实就是把一个大问题进行拆解,把一个大问题拆解成一个个小问题。

案例:
怎么分析下单量下降了。
可以想一些在线购物的流程?你就能想到:一个用户购买商品,会经历几个环节,包括看到广告、点进商品页、点击购买、完成支付等等,最后的订单量下降,我们需要分析那个环节的数据下降了。通过这个方式,你就可以把一个终极的大问题,顺着环节、流程、拆解位一个个过程问题。

漏斗分析案例:你需要认识多少个适龄单身异性才能达到今年脱单的目标。
我们根据恋爱的步骤建立数据漏斗:相遇、相知、相处、相爱。估算一下每个环节的转化率是多少,然后就可以计算出来,最终脱单需要和多少人相遇。

漏斗分析,适用于流程较长、环节较多,并且随着环节进行流量逐渐流失的场景。

漏斗分析的3个应用场景:
1.分析拆解问题,直观的发现和说明问题所在
2.帮助我们分配精力,发现问题后集中尽力解决问题
3.绩效目标管理,比如:一个管理者,需要给团队指定绩效目标,如果定一个笼统的销售额,下属很难完成,因为他很难有能力去思考,到底做什么事情可以提升销售额,所以如果你用漏斗分析出来,我们目前的销售最大的转换问题是用户从试用到下单的环节,那么目标可以不定成销售额,而是定为试用转化率。

漏斗分析三个步骤:
1.根据工作流画出漏斗的各个环节路径
2.对比漏斗各环节做数据分析
3.确定那个环节作为优化重点

思考一下:从流程来看,招聘流程节点有哪些?
我们能够想到的有:发布招聘信息,接受简历,简历初筛,笔试,邀约面试,HR面试,部门经理面,高管面,发Offer,入职,通过试用期。

好,那是不是我们要把这些环节,画成漏斗的形状,形成一个招聘漏斗。
其实不然,我们发现,整个流程节点一共11个,但是如果我们在做漏斗分析的时候,如果把这些节点都放进去,会导致环节过多,反而不利于聚焦。

这里有一个指导原则,就是我们把流程节点转换为漏斗的时候,漏斗的层数最后不要超过7个。
1.归并:对一些节点进行归并。比如,几轮面试可以合并为一层
2.切割:切成不同的漏斗。比如:把发布招聘信息到收到简历,切割为另一个漏斗,比如叫做“简历漏斗”,然后把从邀约到最后入职,切割成一个漏斗,叫做“面试漏斗”

当然,除了自己去思考,实际在各个领域都有固定的漏斗模型,可以直接拿来用。下面是几种常用的漏斗模型。

漏斗1.消费者行为漏斗,简称AIDA模型。AIDA是4个英文单词的首字母,分别对应Attention 注意,Interest 兴趣,Desire 欲望,Action 行为。这个模型意思是,当你希望用户购买某个产品和服务时,应该先吸引他的注意力,再引起他的兴趣,然后勾起其他的欲望,最后促成他行动。

比如:拼多多的广告,先用一个非常洗脑的广告引起注意,“3亿人都在用”这样的广告勾起兴趣,继而用便宜价格激发购买欲望,最后用一些限时拼单等等有紧迫感的活动,促进下单。

漏斗2.用户增长漏斗(海盗模型),用户增长漏斗AARRR模型,近年在互联网领域异常火爆的模型,又被称为“海盗模型”。AARRR,实际上是5个英文单词的首字母,分别代表了Acquisition 用户获取,Activation 促活,Retention 用户留存,Revenue 转化,Referral 转介绍 推荐转发 这5个步骤。

比如:你通过某个广告知道了淘宝,并下载注册了淘宝账户,这个呢,就叫用户获取,注册之后,淘宝会通过推送通知消息,短信等等,来不断刺激你登录,这就要用户促活,主要目的就是希望你不要注册了就再也不来。然后淘宝会通过各种内容,比如直播,会员等等形式,增强你和淘宝的粘性,这个叫用户留存。接着,它还会根据算法,推荐你喜欢的商品,或者推送优惠信息,促使下单,这个叫转化,最后,淘宝通过分享功能,来促使你吧平台商品转发出去,带来新用户。

一些互联网产品,只需要在某个环节做到极致,就可以快速增长,比如拼多多,就是通过拼单的方式,把最后一步转介绍做到极致,从而获取了告诉增长。

漏斗3.营销广告投放漏斗

展示量,点击量,访问量,咨询量,成交量

广告营销界又这样一句话:“我知道花在广告上的钱,一半是浪费的,问题是,我不知道是那一半。”
这种情况,在这个时代,已经越来越少了,每个推广渠道,都可以看见曝光量,用户点击量,用户注册量,甚至购买量,等等。市场人员可以通过各个渠道的数据追踪和分析。及时优化渠道的选择和广告内容。根据这个营销漏斗定位问题,要么优化产品的落地页,要么增强目标投放人群筛选的精准度等,把广告预算花在优质的、有效的渠道。

拆解完漏斗之后,怎么发现问题,单纯的漏斗数据很难发现问题,我们需要通过对比才能发现问题。

历史对比:发现数据和过去又差异,需要回顾 最近做了什么动作,结合历史行为进行分析。
外部对比:发现和外部的差异,能够让我们定位问题和分配精力
横向对比:可以针对不同群体,分别做漏斗数据

做完漏斗数据分析对比,我们可以得到一些结论了,接下来我们要做的是,找到最值的优化的环节。因为找到最值的优化提升的环节,把大问题拆解为更加精准的小问题,才是漏斗分析的最大价值,它可以帮我们聚焦。那么怎么聚焦呢?非常简单,我们使用下面指标来衡量:
1.那个环节优化产出最高
2.优化投入更低

好了,那么到现在为止,一整套分析问题的方法已经形成,总结几个关键点:

1)漏斗分析的本质,是一套分析流程,适用于流程较长,环节较多,并且随着环节进行,流量逐渐流失的场景

2)应用场景:分析拆解问题、帮我们分配精力、绩效管理

3)漏斗分析有三个步骤
步骤一:根据工作流画出漏斗的各个环节路径
步骤二:对漏斗各个环节做数据分析
步骤三:确定那个环节作为优化重点

4)画漏斗的时候,层数最好不超过7层,可以通过归并和切割达到这个要求

5)漏斗数据分析会使用对比的方法:历史对比、横向对比、外部对比

6)确定聚焦那个环节优化的时候,参考2个原则:那个环节优化产出高,以及优化的成本更低

数据分析-发现问题

从数据中发现问题,获取洞见,核心就是对比。

既然要对比数据,就需要回答3个问题。
1、对比什么数据?(what)
2、怎么对比?(how)
3、和谁对比?(who)

数据四大来源
1、从部门KPI和你自己的KPI找
2、从你的工作流里面找
3、从相关的行业报告/行业分析里面找
4、从最近的Excel表格文件找

数据的统计指标和应用
1、平均数、中位数、众数 用来描述数据的集中趋势
2、最值、最大值、最小值 用来描述数据的极端情况
3、比率、比例 用来描述数据比值

如果各个数据之间的差异程度较小,那适合用平均数;如果数据之前差异度较大,或者存在个别的极端值,那用中位数或者众数,更具有代表性。
如果你不知道用什么怎么办?那么就都用上,因为:越多的维度可以对比,就有机会得到更多的洞见。有时候只看绝对数往往无法分析,或者得到的结论是错误的。这时候,比率更能提供指导意见。

和谁对比,常见的对比对象也有3种:历史对比、横向对比、外部对比。
历史对比:用当下的数据,与过去的数据,进行纵向对比。
横向对比:通过横向对比其他要素的情况,来发现和诊断问题。
外部对比:历史和横向对比 都集中在自身或者公司内部,很多时候对比竞争对手可以获取更多的信息。

领导力的四个阶段

The Culture of Leadership

第一阶段:熟悉自己的业务,知道问题在哪里,怎样可以解决。

领导者是给大家指方向的,你必须先知道要走哪个方向,才能带领别人,这是领导力的基础。

第二阶段:培养说服能力,能说服他人,问题可以按照你说的方式解决。

领导力的表现是,他人愿意服从你。这不能都靠制度压服,而要让他人真心觉得你是对的。如果你可以让他人相信你,你就可以领导。

第三阶段:激发他人的热情,让他们产生解决问题的热情。

说服他人的更高境界,是让他们真正投身进来,自觉发挥自己的潜力,全力以赴解决需要解决的问题。好的领导和差的领导,区别就在于能否激励下级,让每个人都知道自己的职责,努力工作。

第四阶段:你培养其他人的领导能力。

如果你离开,团队也能正常运作下去,说明一切已经制度化了,你的领导已经成功了。这时,你可以让其他人接管团队,自己去实现下一个目标。

jar包冲突解决

原文 – 微博

“基础架构部的jar包冲突解决”,这是我们各种中间件sdk最头痛的事情,最怕升级之后sdk的依赖包影响了业务本身的依赖包,或者另一个sdk的。

业界解决方案包括osgi, java modules,springboot式的超级pom文件,各种自产的classloader方案比如蚂蚁金服的SOFAArk,我们也自研了一个但没上线。

最近爱用的方案是maven-shade plugin,将sdk与容易冲突的依赖包如httpclient打包在一起,修改hc的package名比如改成cfgcenter.org.apache,这样就不和谁冲突了,然后坑粗吭哧修改所有import的地方。

天啊,以前我们是自己拉httpclient的源码下来手工修改的,工作量巨大,现在一句plugin配置搞定了,后面都是基于asm的可靠干活。

(但还是人工留意下有没有基于类名反射的情况)

和菜头翻译 如何不靠运气致富

  1. Seek wealth, not money or status. Wealth is having assets that earn while you sleep. Money is how we transfer time and wealth. Status is your place in the social hierarchy.

去寻求财富,而非金钱或地位。财富就是你拥有资产,而资产在你睡觉的时候都还在为你赚钱;金钱是我们转换时间和财富的工具;身份是你在社会等级体系里所处的位置。

  1. Understand that ethical wealth creation is possible. If you secretly despise wealth, it will elude you.

要明白一件事:一个人完全可以不靠坑蒙拐骗站着赚取财富。如果你在暗中鄙视财富,那么财富也会躲着你。

  1. Ignore people playing status games. They gain status by attacking people playing wealth creation games.

别去理会那些热衷于玩身份游戏的人,他们通过攻击那些创造财富的人以获得自己的身份。

4.You’re not going to get rich renting out your time. You must own equity — a piece of a business — to gain your financial freedom.

你不会通过出租自己的时间而变得富有。你必须拥有产权,也就是生意的一部分,以此才能赢得个人财务自由。

5.You will get rich by giving society what it wants but do

es not yet know how to get. At scale.

提供社会大众想要但是他们还不知道如何获取的东西,你就会因此而致富。但有一点:你必须规模化地供应社会。

6.Pick an industry where you can play long term games with long term people.

选择一个你可以长期从事的产业,寻找一批可以一起长期共事的人。

7.The Internet has massively broadened the possible space of careers. Most people haven’t figured this out yet.

互联网极大拓展了一个人职业生涯的可能性。绝大多数人对此毫无认知。

8.Play iterated games. All the returns in life, whether in wealth, relationships, or knowledge, come from compound interest.

玩就玩复利游戏。无论是财富,人际关系或者是知识,所有你人生里获得的回报,都来自复利。

9.Pick business partners with high intelligence, energy, and, above all, integrity.

在选择商业合作伙伴的时候,选择那些高智商、精力旺盛的家伙,但在这一切之上,他应该是个正直诚实的人。

10.Don’t partner with cynics and pessimists. Their beliefs are self-fulfilling.

不要和愤世嫉俗者和悲观主义者合作,因为他们会任由坏事发生,以此证明他们的负面看法是正确的。

11.Learn to sell. Learn to build. If you can do both, you will be unstoppable.

学会如何销售,学会如何创建。如果你同时能做到这两件事,你的成功将无可阻挡。

12.Arm yourself with specific knowledge, accountability, and leverage.

用独到知识,责任感和杠杆武装自己。

13.Specific knowledge is knowledge that you cannot be trained for. If society can train you, it can train someone else, and replace you.

独到知识是那种不可以通过培训而获得的知识。这是因为,如果这种知识可以经由培训而得,那么其他人同样也可以,并且以此取代你。

14.Specific knowledge is found by pursuing your genuine curiosity and passion rather than whatever is hot right now.

在真正的好奇心和热情驱使你前进的路上,你更有可能获得独到知识,而不是在追逐潮流热点的闻风起舞脚步里。

15.Building specific knowledge will feel like play to you but will look like work to others.

创建独到知识的过程对于你就像是在玩,而对于别人则像是工作。

16.When specific knowledge is taught, it’s through apprenticeships, not schools.

不能通过学校教育教会一个人独到知识,它只能通过学徒制口传身教。

17.Specific knowledge is often highly technical or creative. It cannot be outsourced or automated.

独到知识通常极富技术性和创造性,因此它不能被外包或自动实现。

18.Embrace accountability, and take business risks under your own name. Society will reward you with responsibility, equity, and leverage.

拥抱责任感,押上自己的声誉以承担商业风险。社会也会以责任,产权和杠杆作为回报。

19.The most accountable people have singular, public, and risky brands: Oprah, Trump, Kanye, Elon.

最具责任感的人都具有独一无二的、世人皆知的、敢于冒险的个性特征,如奥普拉、川普、坎耶、埃隆。

20.“Give me a lever long enough, and a place to stand, and I will move the earth.” — Archimedes

只要给我一根足够长的杠杆,一处可以立足的地方,我就能撬起地球。——阿基米德

21.Fortunes require leverage. Business leverage comes from capital, people, and products with no marginal cost of replication (code and media).

财富增长需要使用杠杆。商业杠杆有三个来源:1、资本;2、人力;3、复制起来边际成本为零的产品(如:代码和媒体)。

22.Capital means money. To raise money, apply your specific knowledge, with accountability, and show resulting good judgment.

资本的意思就是钱。想要融资,那就运用你的独到知识,配合你责任感,展示出你良好的判断力。

23.Labor means people working for you. It’s the oldest and most fought-over form of leverage. Labor leverage will impress your parents, but don’t waste your life chasing it.

人力指的就是为你干活的人,它是最古老也是争夺最激烈的杠杆。人力杠杆会让你父母因为你手下有许多人为你工作而感到骄傲,但你不要浪费生命去追求这一点。

24.Capital and labor are permissioned leverage. Everyone is chasing capital, but someone has to give it to you. Everyone is trying to lead, but someone has to follow you.

资本和劳动力是需要征得许可才能使用的杠杆。每个人都在追逐资本,但总得有个什么人给你才行;每个人都想要领导其它人,但总得有什么人愿意跟着你才行。

25.Code and media are permissionless leverage. They’re the leverage behind the newly rich. You can create software and media that works for you while you sleep.

代码和媒体是无需要许可即可使用的杠杆。它们是新贵人群背后的杠杆,你可以通过自己创建的软件和媒体,在睡觉时仍然为你干活。

26.An army of robots is freely available — it’s just packed in data centers for heat and space efficiency. Use it.

一支机器人军团已经集结待命,只是为了节约空间和热效能,它们被打包放进数据中心。去用吧。

27.If you can’t code, write books and blogs, record videos and podcasts.

如果你不会编程,那你还可以写书和博客,或者做视频或者音频节目。

28.Leverage is a force multiplier for your judgement.

杠杆能够成倍地放大你的判断力(所产生的效能)。

29.Judgement requires experience, but can be built faster by learning foundational skills.

判断力需要经验,但它可以通过学习基本技能的方法更快速地建立起来。

30.There is no skill called “business.” Avoid business magazines and business classes.

并不存在一种叫做“商业”的能力。尽量避开商业杂志和商业课程。

31.Study microeconomics, game theory, psychology, persuasion, ethics, mathematics, and computers.

去学习微观经济学、博弈论、心理学、说服术、伦理学、数学和计算机科学。

32.Reading is faster than listening. Doing is faster than watching.

读比听快,做比看快。

33.You should be too busy to “do coffee,” while still keeping an uncluttered calendar.

你应该忙得没有社交的时间才对,与此同时你应该始终保证日程安排井井有条。

34.Set and enforce an aspirational personal hourly rate. If fixing a problem will save less than your hourly rate, ignore it. If outsourcing a task will cost less than your hourly rate, outsource it.

你应该为自己设定一个有抱负的个人时薪数,并且坚持执行。如果解决一个问题所能节省下来的成本低于你的个人时薪,那就忽略这个问题好了;如果一项任务的外包成本低于你的个人时薪,就把它外包出去。

35.Work as hard as you can. Even though who you work with and what you work on are more important than how hard you work.

尽管你跟谁一起工作、做什么工作,要远比你的努力程度更加重要。但还是要倾尽全力去工作。

36.Become the best in the world at what you do. Keep redefining what you do until this is true.

你所做的事情,要努力做到世界最好。不断重新定义你在做什么,直到真的做到世界最好。

37.There are no get rich quick schemes. That’s just someone else getting rich off you.

这个世界上并没有快速赚钱致富的方法,如果你想要找寻这种方法,那它只会让别人从你身上赚钱致富。

38.Apply specific knowledge, with leverage, and eventually you will get what you deserve.

运用你的独到知识,配合上杠杆,最终你会得到你应该得到的东西。

39.When you’re finally wealthy, you’ll realize that it wasn’t what you were seeking in the first place. But that’s for another day.

终有一天当你变得富有,你会发现那一切并不是你最开始想要的东西。但是那就是另外一回事了。

注释:

1、财富就是你睡着觉,你的资产也在为你继续赚钱。这是一个越来越被广泛接受的定义。Naval Ravikant是硅谷狂热的数字货币支持者,所以,他的话另有所指。从前后文来看,他所谓的资产并不等于是传统意义上的房产、股票、收藏,而是偏向于他反复提及的:软件和媒体。

2、出租时间概念,许多人理解为打工,认为打工就是出租自己的时间以换取金钱。其实并非如此,Naval所指的出租时间概念,指的是一个人的财富增长,是否直接关系到他的时间。一个小卖部的老板,他并不为谁打工,但是他的财富增长需要他长时间守在店里,因此,他依然是出租时间换钱。但一个淘宝点卡店老板则不同,他的点卡销售是全自动的,不需要24小时守着,而且也不需要只做这一样生意。这就是Naval所谓互联网拓宽了个人职业生涯的一个例子。

3、equity我翻译为产权,不是一个很好的翻法。但是Naval前文提到assets,很明显,作为投资人他非常清楚地知道这两个字眼之间的区别。equity无论是翻译为股票、权益或者是资产,原文说“ You must own equity — a piece of a business — to gain your financial freedom.”,这是和出租时间概念做对应的。出租时间的人,在商业链条里作为生产资料出现,不拥有任何产权,也就无法通过商业行为获利,所以,我这里勉强翻译为产权。

4、specific knowledge我翻译为独到知识,没有翻译为特定知识、专业知识或者是特殊知识。原因是在我的理解中,specific knowledge不是书本知识,也不是学校教授的知识,更不可能在网上免费获取。一方面,它只能提供自己实践来获取;另一方面,它只能通过前人口耳相传。这种知识是做成一件事情的关键,属于知识体系中不共的那一部分。所以,我翻译为独到知识。

5、“Give me a lever long enough, and a place to stand, and I will move the earth.” — Archimedes 这话不像是阿基米德说的。更像是一次抬杠的结果:

“给我一个支点,我就能撬起地球!”

“那么,您站在哪儿呢?”

“好吧,给我一个支点,再给我一个站立的地方,我就能撬起地球。”

“那么,您用空气就能撬起地球了?”

“好吧,给我一根足够长的杠杆,一处可以立足的地方,我就可以翘起地球!”

“那么,阿基米德先生,支点又不需要了吗?”

“滚!”

6、accountability我本想翻译为“靠谱程度”,想想还是算了。

7、号称是“四十条语录”,但是我就找见了39条。

8、结合上下文看,Leverage一词始终翻译为“杠杆”其实也不大对头。Naval一再强调代码、博客、播客、视频节目,我觉得Leverage在他那里,有些时候应该相当于是个人影响力的代名词,或者可以简单理解为放大器。