硅谷增长黑客实战笔记

硅谷增长黑客

概念

增长黑客这一概念起源于美国互联网行业,最早由 Sean Ellis 提出,已经帮助硅谷多家公司完成产品的快速增长。其中最著名的案例包括 Dropbox,Hotmail,Facebook。近年来,增长黑客的概念传到国内,也引起了众多创业者的关注。

增长黑客本身是一套产品管理理论框架,并不是一套实践框架,如何才能真正地对公司产生价值呢?除了有一个完善的增长团队,还需要有产品作为内容,工具作为执行手段。

增长的精髓是一套体系和方法,它以数据为指引,以实验的方式,系统性地在用户生命周期的各个阶段(包含用户的获取、激活、留存、推荐、变现、回流等),虚招当下性价比最高的机会,在具体的执行上横跨市场、产品、工程、设计和数据等团队,通过快速迭代实验的方式达到目标。

结果可量化、方法可重复、过程可迭代(量化,公式化即模型化,迭代化)

Mac 下 brew 切换为国内源

简介

Homebrew 是一款自由及开放源代码的软件包管理系统,用以简化 macOS 和 linux 系统上的软件安装过程。它拥有安装、卸载、更新、查看、搜索等很多实用的功能,通过简单的一条指令,就可以实现包管理,十分方便快捷。

Homebrew 主要有四个部分组成: brewhomebrew-corehomebrew-bottleshomebrew-cask

名称 说明
brew Homebrew 源代码仓库
homebrew-core Homebrew 核心软件仓库
homebrew-bottles Homebrew 预编译二进制软件包
homebrew-cask 提供 macOS 应用和大型二进制文件

tmux使用

系统操作

1
2
3
4
5
? 列出所有快捷键;按q返回
r 强制重绘未脱离的会话
: 进入命令行模式;此时可以输入支持的命令,例如kill-server可以关闭服务器
[ 进入复制模式;此时的操作与vi/emacs相同,按q/Esc退出
~ 列出提示信息缓存;其中包含了之前tmux返回的各种提示信息

会话

1
2
3
4
5
6
7
8
9
tmux new -s basic  新建会话,basic为会话名称
exit 退出会话
tmux ls 列出会话
tmux attach -t sessionid 进入会话
tmux kill-session -t sessionid
d 脱离当前会话;这样可以暂时返回Shell界面,输入tmux attach能够重新进入之前的会话
D 选择要脱离的会话;在同时开启了多个会话时使用
Ctrl+z 挂起当前会话
s 选择并切换会话;在同时开启了多个会话时使用

窗口

1
2
3
4
5
6
7
8
9
10
11
tmux new -s basic -n shell 新建session名字为basic,窗口名字为shell
c 创建新窗口
& 关闭当前窗口
数字键 切换至指定窗口
p 切换至上一窗口
n 切换至下一窗口
l 在前后两个窗口间互相切换
w 通过窗口列表切换窗口
, 重命名当前窗口;这样便于识别
. 修改当前窗口编号;相当于窗口重新排序
f 在所有窗口中查找指定文本

面板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
" 将当前面板平分为上下两块
% 将当前面板平分为左右两块
x 关闭当前面板
! 将当前面板置于新窗口;即新建一个窗口,其中仅包含当前面板
Ctrl+方向键 以1个单元格为单位移动边缘以调整当前面板大小
Alt+方向键 以5个单元格为单位移动边缘以调整当前面板大小
Space 在预置的面板布局中循环切换;依次包括even-horizontal、even-vertical、main-horizontal、main-vertical、tiled
q 显示面板编号
o 在当前窗口中选择下一面板
方向键 移动光标以选择面板
{ 向前置换当前面板
} 向后置换当前面板
Alt+o 逆时针旋转当前窗口的面板
Ctrl+o 顺时针旋转当前窗口的面板
Alt+方向键 调整面板大小

正则表达式总结

DFA和NFA

DFA和NFA反映了正则表达式在应用算法上的根本差异,NFA为表达式主导,DFA为文本主导,有什么区别呢?

  • 表达式主导:

    如用正则表达式:to(nite|knite|night) 来匹配文本:tonight,正则表达式中第一个是‘t’,他会重复尝试,知道在匹配文本中找到‘t’为止,之后检查后续文本是否匹配‘o’,如果能,会接着检查选择分支,引擎会依次尝试‘nite’,‘knite’,‘night’这三种可能,直到匹配成功或全部尝试完后匹配失败,在匹配‘nite’时,会想上面一样一次匹配‘n’,‘i’,‘t’,‘e’,如果失败,在尝试另一种可能。表达式中的控制权在不同的元素之间转换,所以称之为“表达式主导”。

  • 文本主导:

    DFA引擎在扫描字符串时,会记录当前有效的所有可能匹配,如上例中,当扫描到匹配文本的‘i’字符时,它会记录下两个可能匹配的位置‘nite’中的‘i’和‘night’中的‘ni’,从而把knight淘汰,再扫描匹配文本中的‘g’,这时只有‘night’能匹配,只剩下一种可能,然后依次匹配‘h’和‘t’,引擎发现匹配已经完成,报告成功。它是扫描的字符串中的每个字符都对引擎进行了控制,所以称为“文本主导”。

NFA效率会低于DFA,因为DFA每个字符只会扫描一次,而NFA对同一字符会扫描多次。

Effective Java笔记

创建销毁对象

Item1: 使用静态工厂代理构造器

优点:

1.静态工厂可自定义名字,见名知意,如BigInteger(int, int, Random)BigInteger.probablePrime.有时多个构造器会让人无从选择,容易出错。
2.静态工厂不需要每次调用都创建一个对象。对于某些对象可以重复利用的场景,这种方式效率更高。
3.静态工厂可返回方法返回对象的任意子类,基于接口编程。
4.静态工厂可根据输入参数来创建不同的返回对象
5.静态工厂可以仅仅是一个占位符,根据注入的不同服务,返回不同的对象,如JDBC
缺点:
1.如果类中不包含publicprotected的构造函数,将无法被继承
2.难以区分那些是静态工厂方法,那些是普通的静态方法,通常使用方法名称区分,如of,from,valueOf,getInstance

Item2: 若构造器需要很多参数的时候,考虑使用建造者模式

当构造器需要多个参数,而且部分参数可选的时候,通常有几种处理方式:
1.使用构造器重载,默认参数在简单的构造器中设置,简化客户端调用。
缺点:在参数很多的时候,组合的情况很多。代码难写也难读。
2.使用JavaBean的方式,初始化设置属性的默认值,使用set方法来设置必要的参数。
缺点: 会导致不一致的问题,参数没设置完整,对象已经是可用的。另外会让对象变得可变,多线程就得考虑线程的安全
3.使用建造者模式,Builder使用链式调用,每设置一个参数,返回的是本身,设置完所有的参数,调用build 方法的时候,将构造器传入给要新建的对象,通过构造器设置完参数后,返回。

Item3: 使用私有构造器或者枚举类型来强化单例属性

三种方式:
1.public static final INSTANCE= new Singleton(),私有化构造器,简单直接
2.私有化属性,私有化构造器,静态工厂返回单例,如果不需要对单例对象加工,也不需要使用范型,也不需要使用suppler,如Singleton::INSTANCE,则使用第一种方式
3.使用枚举来实现,通常作为最佳实践

Item4: 通过私有化构造器来强化不可实例化的能力

一些工具类只包含静态方法,静态变量,不需要被继承和实例化,此时采用私有化构造器来保证其不被实例化和继承。

Iemt5: 采用依赖注入来取代硬编码

资源使用依赖注入比使用静态工厂或静态工具类更灵活更容易测试。

Item6: 避免创建不必要的对象

不可变对象复用,原生类型的装箱拆箱。

Item7: 消除过期对象的引用

不再引用的对象置为null,绝大部分情况不需要设置,若在作用域以外仍然会引用废弃的对象,才需要设置。自己管理内存或者对象的情况下,需要考虑。

Item8: 避免使用终结方法

Finalizers不可预料,危险通常是不必要的。JAVA9不推荐使用Finalizers,以Cleaners取而代之,比Finalizers安全,同样不可预料,影响性能,没有必要使用。因为不知道终结方法何时执行。Finalizers会吞噬异常,Cleaners不会吞噬异常。作为安全网或者是终结非关键的本地资源,否则不要使用终结方法。

Item9: 使用try-with-resources代替try-finally

对所有对象都通用的方法

Item10: 覆盖equal的时候遵守通用约定

1.自反性 对于非空对象,x.equal(x)返回ture
2.对称性 x.equal(y)y.equal(x) x,y为继承关系,容易出现违反对称性,因为调用不同的equal方法。
3.传递性 x.equal(y),y.equal(z)x.equal(z) y为父类,x,z为子类,容易违反传递性,将子对象转换成父对象比较,都相等,子对象里判断了其他属性,导致两个子对象不相等。只要父类不可实例化,就不会违反传递性。
4.一致性 在不修改x,y的情况下,x.euqal(y)不变,如果依赖了不可靠的资源,比如域名对应ip,就容易违反。
5.任何非空x,x.equal(null)返回false

我们无法在扩展可实例化的类的同时,即增加新的属性,又保留equal的约定。
实现高质量的equal步骤:
1.使用==判断是否相同的引用
2.使用instanceof检验参数的类型是否正确
3.将参数转换成正确的类型
4.检查关键的字段是否一致
5.考虑对称性、传递性、一致性
实现equal要注意equal的参数是Object类型,如果改成其他类型的,就不是重写,而是重载。重写时使用override注解,重写错类,会提示编译错误。

Item11: 覆盖equal时,一定要覆盖hashcode

相等的对象,hashcode一定相等,不相等的对象,hashcode也可能相等。因此,equal里用到的关键字段,在hashcode的计算时,都应该用到,在equal里没有用到的字段,不要用于hashcode计算。
hashcode计算规则:
1.初始化一个reuslt值,步骤2循环关键字段
2.根据字段计算c,如果字段是原生类型,则调用Type.hashCode(f),如果字段是引用类型,则调用对象的hashCode,如果是数组,使用Arrays.hashCode
3.result = 31* result + c,重复循环计算关键字段。

Item12: 始终覆盖toString

Item13: 谨慎地覆盖clone

Item14: 考虑实现Comparable

类与接口

Item15: 使类和成员的访问最小化

Item16: 在公有类中使用访问方法,不使用公有域

Item17: 使可变性最小化

实现不可变类:
1.不提供任何会修改对象的方法
2.保证类不会被扩展
3.使所有的域都是final
4.使所有的域都成为私有的
5.如果域是可变的,则不让改域能在外部访问,也不要返回可变的域,也不要使用外部传入的可变对象来初始化域

Item18: 组合优与继承

继承破坏了封装。继承其他人编写的具体类时,要有文档说明可以被继承,否则容易出错。只有在确实子类是父类的子类型,采用继承,否则用组合。

Item19: 为继承做好设计,并文档化,否则就不要用继承

Item20: 接口优于抽象类

Item21: 做好接口设计

虽然默认接口能实现在接口里添加方法,不影响原来的实现。但是不要这么做,因为可能导致运行时的问题。默认方法可用于提取接口实现的公有逻辑,不要用来修改接口。

Item22: 接口只用于定义类型

不要使用常量接口,常量可以使用工具类来实现。

Item23: 类层次优于标签类

Item24: 优先考虑静态成员类

Item25: 限制一个文件定义多个顶级类

泛型

Item26: 不要使用原生类型

Item27: 消除非受检警告

尽量消除,无法消除的使用注解SuppressWarnings("unchecked"),并注明原因,SuppressWarnings("unchecked")范围越小越好。

Item28: 列表优先于数组

Item29: 优先考虑泛型

Item30: 优先考虑泛型方法

Item31: 利用有限制通配符来提升API的灵活性

Item32: 明智的组合泛型和可变参数

Item33: 优先考虑类型安全的异构容器

枚举和注解

Item34: 用enum代替int常量

Item35: 用实例域代替序数

Item36: 用EnumSet代替位域

Item37: 用EnumMap代替序数索引

Item38: 用接口模拟可伸缩的枚举

Item39: 注解优先于命名模式

Item40: 坚持使用Override注解

Item41: 用标记接口定义类型

lamda与stream

Item42: lamda优先于匿名类

优先使用lamda,lamda由于没有名字和文档,所以表达式应该清晰明了,代码不要超过3行,。大部分使用匿名类的场景都可以使用lamda替换,除非要使用多个函数。

postgresql总结

centos安装postgresql

1
2
3
4
5
6
7
yum install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-centos96-9.6-3.noarch.rpm
yum install postgresql96
yum install postgresql96-server
service postgresql-9.6 initdb
chkconfig postgresql-9.6 on
service postgresql-9.6 start

添加用户

1
2
3
4
5
6
7
8
9
sudo adduser dbuser
sudo su - postgres
psql
#进入数据库控制台,可设置密码,创建用户和数据库,授权
\password postgres
CREATE USER dbuser WITH PASSWORD 'password';
CREATE DATABASE exampledb OWNER dbuser;
GRANT ALL PRIVILEGES ON DATABASE exampledb to dbuser;
\q

控制台命令

  • \h:查看SQL命令的解释,比如\h select。
  • \?:查看psql命令列表。
  • \l:列出所有数据库。
  • \c [database_name]:连接其他数据库。
  • \d:列出当前数据库的所有表格。
  • \d [table_name]:列出某一张表格的结构。
  • \du:列出所有用户。
  • \e:打开文本编辑器。
  • \conninfo:列出当前数据库和连接的信息。
  • \q 退出数据库控制台
  • \password 修改密码

树莓派使用总结

osx安装XBian

  1. 下载 XBian image 文件
  2. 将sd卡插入电脑,执行df -h查看SD卡盘符
  3. 执行一下命令,盘符根据情况改变
    1
    2
    sudo diskutil unmount /dev/disk3s1
    sudo dd bs=1m if=~/Desktop/xbian.img of=/dev/disk3s1
  4. 开始安装到 SD 卡了,按 ctrl + t 可以看到安装过程。安装完后你会看到 xxxx bytes transferred in xxx secs 字样
  5. 输入 sudo diskutil eject /dev/rdisk? 安全拔出 SD 卡
  6. 把 SD 卡插入 Raspberry Pi,启动就可进入安装了。安装完后直接就是 XBMC 界面了。

visual studio总结

快捷键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ctrl+-shift+ctrl+-):移动光标到上次位置或相反,比如定位一个函数,转到函数定义后想回到函数使用处,则用ctrl+-,若又想回到函数定义处则可以按shift+ctrl+-
F12Go to Definition,到变量或函数定义的地方,如变量声明处,函数实现处。与ctrl+-配合使用非常方便

Ctrl+]:匹配选中的括号(大括号、小括号都行),在多层循环+判断语句时非常方便

ctrl+Space:代码补全

ctrl+tab:在VS中切换打开的窗口,即切换各个文件

ctrl+I:递增搜索,与ctrl+F不同的是搜索期间不显示搜索对话框,且ctrl+F搜索下一个直接按Enter即可,而ctrl+I搜索下一个按ctrl+IF3Escape退出,连续按两次ctrl+I重复上次搜索
Ctrl+Shift+F:旧式的文件搜索对话框(与记事本中的搜索替换框差不多,可以替换)
Ctrl+F3:为当前选中的部分进行搜索(不需要再输入要搜索的内容)

Shift+Alt+Enter:最大化代码编写区域(代码全屏模式),即去掉所有其它辅助窗口只留下代码编写窗口,再按一次返回到原来界面

ctrl+KCtrl+C:注释一段代码块(先要选中一段代码)
ctrl+KCtrl+U:取消注释一段代码块
ctrl+KCtrl+D:代码自动格式化(整个文档)
ctrl+KCtrl+F:只格式化你选中的部分


Ctrl+KCtrl+K:在当前行创建一个书签
Ctrl+K, Ctrl+N:去下一个书签处


Ctrl+C, Ctrl+V:在当前行的下一行复制当前行内容(不用选中当前行),即复制当前行并粘贴到下一行,在两行内容差不多时很有用,可以先复制再改
Ctrl+L:删除当前行

Ctrl+M, Ctrl+M:展开或关闭当前的代码

centos安装php5.6

配置yum源

centos6

1
2
# rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

centos7

1
2
# yum install epel-release
# rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

查看可安装的包

1
# yum list --enablerepo=remi --enablerepo=remi-php56 | grep php

安装php5.6

1
yum install --enablerepo=remi --enablerepo=remi-php56 php php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit php-pecl-xdebug php-pecl-xhprof php-soap php-fpm

mysql日常运维

centos安装mysql

1
2
3
4
5
6
7
8
9
10
11
12

#下载文件
mwget http://cdn.mysql.com/Downloads/MySQL-5.6/MySQL-5.6.25-1.linux_glibc2.5.x86_64.rpm-bundle.tar

#查询是否安装
rpm -qa|grep mysql

#删除已安装的mysql
rpm -e -allmatches -nodeps mysql-libs-5.1.73-3.el6_5.x86_64

#启动mysql
/etc/init.d/mysql start

mysql无法登陆

1
2
3
4
5
6
7
8
9
10
11
12

# /etc/init.d/mysql stop
# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &
# mysql -u root
mysql> use mysql
mysql> UPDATE user SET Password=PASSWORD('root') where USER='root';
mysql> FLUSH PRIVILEGES;
mysql> quit
# /etc/init.d/mysql restart
# mysql -uroot -p
Enter password: <输入新设的密码newpassword>
mysql> SET PASSWORD = PASSWORD('newpasswd');

导出csv文件

1
2

mysql icms -uroot -e "SELECT column AS '列名' FROM table " >bond.xls

导出数据库

1
mysqldump -uroot -ppassword dbname > dbname-backup-$(date +%Y%m%d).sql

授权并创建用户

1
2
grant all on dbname.* to root@'localhost' identified by 'pass';
flush privileges;

删除用户

1
drop user user@'%';