OKR之我见

OKR(Objectives and Key Results)全称为“目标和关键成果”,是一种管理方法。

当然,对于熟悉上下文大环境的人来讲,设立承诺型或挑战性的目标与关键结果没什么问题。但是对于新人来说,就比较困难了,倘若不给他先期的目标设置、要求与预期的确立,他怎么能进行特定的知识探索,怎么能快速的、深入的了解上下文环境?只是凭个人吭哧吭哧的了解,然后再来建立自己的okr?

先不说效率问题。有道是师傅领进门,修行在个人,问题是新人面对庞大的陌生领域,门还没找见呢,也没个mentor引导就纯凭自己探索?这就是变向劝退啊,新人友好度太次了,如果个人耐心不足,可能说走就走了。

如果我是主管,新人入伙,一定要这样安排:
1.头2天任由新人自由发挥,完成公司级别的行政、it事件。差不多第3天开始,安排部门级别的新手攻略。

2.攻略主要内容,包括认识主要业务,上手职位工作。认识主要业务不是泛泛的说只是让新人自己去看看相关百科资料,而是确实的指出什么环境,什么操作,将最能直接获得反馈的事件,1--2--3的列出,去做,让新人有的放矢,深入浅出,减少新人隔阂感。

速度快的话,完成一个模块的运转,再給他一个模块,1234-2234,不出几周吧,新人就能主动思考okr了,这里的重点是:一定要让新人循序渐进,有事可做,减少摩擦、减少不必要的离职风险。


以上,总结一下就是:
没有引导,让新人直接 okr == 压力测试 >= 劝退。

后端性能测试总结

三个指标:

并发用户数:取决于 业务并发用户数 和 用户行为模式。

响应时间:前端+后端响应时间。

系统吞吐量:是最能直接体现软件系统负载承受能力的指标。 Requests/Second ,系统吞吐量是最能直接体现软件系统承受负载能力的指标,但也必须和其他  指标一起使用才能更好地说明问题。

并发用户数、响应时间、系统吞吐量之间的关系:

阶段1 :空闲区间
2:  线性增长区间
3:  拐点:系统的处理能力逐渐趋于饱和
4: 过饱和区间:系统处于被压垮的状态。
  • 后端性能测试的测试负载,我们一般只会把它设计在“线性增长区间”内;而压力测试的测试负载,我们则会将它设计在系统“拐点”上下,甚至是“过饱和区间”。

测试方法:

  • 后端性能测试:是通过性能测试工具模拟大量的并发用户请求,然后获取系统性能的各项指标,并且验证各项指标是否符合预期的性能需求的测试手段。

    根据应用领域的不同,后端性能测试的场景设计主要包括以下两种方式:

    1.基于性能需求目标的测试验证;

    2.探索系统的容量,并验证系统容量的可扩展性。

  • 压力测试,通常指的是后端压力测试,一般采用后端性能测试的方法,不断对系统施加压力,并验证系统化处于或长期处于临界饱和阶段的稳定性以及性能指 标,并试图找到系统处于临界状态时的主要瓶颈点。所以,压力测试往往被用于系统容量规划的测试。

  • 配置测试,主要用于观察系统在不同配置下的性能表现,通常使用后端性能测试的方法:通过性能基准测试(Performance Benchmark)建立性能基线(Performance Baseline);在此基础上,调整配置;基于同样的性能基准测试,观察不同配置条件下系统性能的差异,根本目的是要找到特定压力模式下的最佳配置。这里需要注意的是,“配置”是一个广义配置的概念,包含了以下多个层面的配置:宿主操作系统的配置;应用服务器的配置;数据库的配置;JVM 的配置;网络环境的配置等。

  • 并发测试,指的是在同一时间,同时调用后端服务,期间观察被调用服务在并发情况下的行为表现,旨在发现诸如资源竞争、资源死锁之类的问题。

  • 可靠性测试,是验证系统在常规负载模式下长期运行的稳定性。时间长度跨越单位通常为天。

性能测试的四大应用领域:

web网站架构设计

1.高性能设计:

  • 前端高性能设计主要是:加快用户实际感受到前端页面展示的时间。主要受网络延时和资源加载因素影响。
  • 后端高性能设计:
    1) 使用缓存加快处理时间,降低后端运算负载。
    2) 服务器集群化,前置负载均衡,提高计算性能和并发能力。

2.高可用设计:

  • 后端服务器至少2台,前置一台负载均衡器,实现应用服务高可用。
  • 分布式数据存储,实现数据高可用。

3.伸缩性设计:
基于机器的集群的进行可伸缩性设计,或者基于一台机器的硬件配置进行伸缩。

基于集群的进行可伸缩性设计:

- 横切:单一功能按层次划分,例如购物功能,可以划分为:
|ui层|
|业务逻辑层|
|公共服务层|
|数据存储层|
每一层都可以独立实现可伸缩。

- 纵切:按业务种类垂直划分,物理隔离服务。比如:
按|用户管理|购物|支付|划分,而且|购物|业务按业务范围
还可以向下划分为:
|百货|电子产品|生鲜|

这样纵切得到的|购物-百货|业务,按照购物功能的横切划分,拥有自己的一套执行环境,即为:
ui静态服务器,
业务逻辑服务器集群,
数据存储服务器、集群。
而公共服务层可以抽象为一个业务,具有自己的集群。

web性能优化

web 性能优化:

1.基本方法:

a.客户端文本资源 minification。

比如 npm install –g minifier html-minify。
minify .css,.js。
htmlminify .html。

b.服务器开启压缩技术

c.优化图片 tinyPng

2.优化 css:

CSS shorthand properties not only are convenient, but also offer us a way to reduce the size of our style sheets by cutting down on excessive and verbose rules.

Using shallow CSS selectors can also significantly reduce the size of a style sheet, as well as make code more maintainable and modular.

Applying the DRY principle with the csscss redundancy checker can further winnow bloated CSS files by enabling you to remove superfluous properties.

避免使用@import。@import 会串行化资源请求。
尽量使用 <link>。可以并行化请求。 # 针对http1.x。

<head>里提前放置 css。
理由:
1) 防止flash of unstyled content 出现。
2) 减少 re-render and repaint the entire DOM.

使用性能更快的选择器。常见的 tag: div,descendant: div ul li ,class: .listitem,direct child: section > ul > li 性能都差不多,其他的 Sibling,Pseudo,Attribute 比较慢。

尽可能使用 flexbox 布局。

例如有 flexbox style:
        parent:> display: flex; justify-content: space-between; flex-flow: row, wrap;
        children: > flex-basis: 24.25%

比较 box model:
        parent: > display:block。
        children:> width: 24.25%;
        往往还会用到 :nth-child selector 调整尾端

The conclusion you can draw is that when it comes to rendering content, flexbox tends to be a better-performing solution. Better yet, it enjoys broad support without vendor-specific prefixes. When used with vendor prefixes, support only increases. If you’re not using flexbox on your websites, it’s rather trivial to retrofit in most cases.

3.images responsive:

  • Delivering responsive images in CSS with media queries, and how supplying the correct image sources to the proper devices can positively impact loading and processing time

  • Delivering responsive images in HTML by using the srcset attribute and the <picture> element

  • Providing polyfill support for the <picture> element and srcset attribute for older browsers in an optimal fashion

  • Using SVG images in both CSS and HTML, and the convenience and flexibility inherent to the format when it comes to optimal display on all devices

4.images else:

  • reduce size, compression or optimizing.
  • use webp.
  • lazy loading images.

5.fonts.

  • 只选择需要 weight 字体
  • 用 css @font-face 确定使用字体
  • 使用 font-display 声明字体未加载时策略
  • 使用 subset 减少字体文件大小

e.g.

@font-face{
    font-family: "Open Sans Light";
    font-weight: 300;
    font-style: normal;
    src: /*
         These local sources are commented out for debugging purposes.
         In any production site, they should be enabled.
         local("Open Sans Light"),
         local("OpenSans-Light"),
         */
         url("open-sans/OpenSans-Light-BasicLatin.woff2") format("woff2"),
         url("open-sans/OpenSans-Light-BasicLatin.woff") format("woff"),
         url("open-sans/OpenSans-Light-BasicLatin.eot") format("embedded-opentype"),
         url("open-sans/OpenSans-Light-BasicLatin.ttf") format("truetype");
         font-display: swap;     # local fallback
         unicode-range: U+0000-007F;    # subset
}  

6.script

- Depending on its position, the <script> tag can block rendering, which delays the display of the page in the browser. Placing <script> tags toward the bottom of the document can speed up the rendering of a page.
- The async attribute can provide further performance benefits if you can manage the execution of scripts that use it.
- Managing the execution of interdependent scripts that use async can be challenging. A third-party script-loading library such as Alameda or RequireJS can provide a convenient interface for managing script dependencies, while also providing the benefit of asynchronous script loading and execution。

7.cache assets

  • 使用 cache contorl:

    no-cache、no-store、stale-witle-revalidate && max-age
    对于各种资源的缓存策略举例:

  • 使用 cdn 资源。举例:

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> 

8.http2

Techniques that reduce the size of assets are things you should still do on HTTP/2. These are techniques such as minification, server compression, and image optimization. Reducing the size of an asset contributes to lower load times, always and forever.

Techniques that combine files are things you should stop doing on HTTP/2. Although useful in alleviating latency in HTTP/1 client/server interactions, requests are much cheaper in HTTP/2, and combining files can have an adverse effect on your caching effectiveness.
  • http2 不去捆绑资源主要是考虑缓存。在一个tcp连接之下,请求更颗粒化,多次请求,延迟不是问题。不过传递资源始终会经历延时,所以内敛化资源比如 css 还是有效。

  • server push 是个好特性,这篇文章包含 preload hint、server push 和 No optimization 的对比:
    https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/

  1. 使用 gulp 自动化以上任务。
    https://github.com/pluckhuang/useGulp

OLOO in JavaScript

在 Js 里 "OLOO" (objects-linked-to-other-objects) 较 OO (object-oriented):

  • 心智模型更直接
  • 语法更简洁
  • 生成的对象更少
  • 而 ES6中对 Class 的支持,只是可读性更好,本质上还是走原型委托。但是引用的 super 是静态绑定。而且还是会动态改变。

所以如果建模的话,选择 OLOO 。

refer https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/objects-classes/ch6.md#review-tldr

JavaScript 普通函数、箭头函数和this

  • 作为对象属性的普通函数,this 绑定为该对象。

  • 作为回调函数的普通函数,this 绑定为被触发对象。

  • 除了 call、apply、bind 以外能指定 this 参数,其余调用普通函数的地方,this 都绑定为全局对象。

  • 箭头函数没有自己的 this,也就是说没有自己的定义域。进一步说,就是会绑定定义时上层代码块的 this。

function Timer() {
    this.s1 = 0;
    this.s2 = 0;
    // 箭头函数
    setInterval(() => this.s1++, 1000);
    // 普通函数
    setInterval(function () {
        this.s2++;
    }, 1000);
}

假如 var timer = new Timer();
此时 timer.s1 可以正常绑定,.s2 被绑定到了全局对象。

再假如,直接调用函数 Timer(),此时 s1 也被绑定到了全局对象。
  • 即使作为对象方法,箭头函数内部的 this 也是指向的全局对象。所以箭头函数不适合作为函数方法。
  • 作为回调函数的箭头函数,this 绑定为全局对象。所以箭头函数不适合动态指定 this 的场合。
var x = 10;

let foo = {
  x: 20,

  // Dynamic `this`.
  bar() {
    return this.x;
  },

  // Lexical `this`.
  baz: () => this.x,

  qux() {
    // Lexical this within the invocation.
    let arrow = () => this.x;

    return arrow();
  },
};

console.log(
  foo.bar(), // 20, from `foo`
  foo.baz(), // 10, from global
  foo.qux(), // 20, from `foo` and arrow
);

一道有意思的Js 题,sum(1,2)(3,4).sumof()…

看到一道题有点意思:

题目:编写函数方法实现
  • 形式1:sum(1).sumof()
  • 形式2:sum(1,2).sumof()
  • 形式3:sum(1)(2, 3).sumof()
  • 最终求得的结果,需要是各个出现的数字的和。
目前想到的写法:
function sum(...lastArgs) {
    var callback = function(...args) {
        return sum(...[ ...lastArgs, ...args ]);
    };
    callback.sumof = function() {
        return lastArgs.reduce((aggregated, number) => aggregated + number, 0);
    };
    return callback;
}

为什么 promise 结合生成器使用更优雅?

promise 用来执行异步任务。

通过链式调用可以一步接一步的执行任务,那么为什么还要结合生成器呢?

比如这样的:

new promise(...).then(val1 => {resolve(val2)}).then(val2 => resolve()).catch();

变成这样的:

function* xx() {
    const val1 = yield new promise(...);
    const val2 = yield new promise(...);
}

最终产生了 async?
变成这样:

async function xx() {
    const val1 = await new promise(...);
    const val2 = await new promise(...);
    return
}

答案是用【同步写法】执行【异步任务】,这样看代码看的更清楚。而且使用了 async,还包括了自动执行,可以直接调用xx()来得到结果。