wangpin34 / blog

个人博客, 博文写在 Issues 里
5 stars 0 forks source link

2021/09/10: 给自己立个 flag #76

Open github-actions[bot] opened 3 years ago

github-actions[bot] commented 3 years ago

封面

artem-maltsev-3n7DdlkMfEg-unsplash Photo by Artem Maltsev on Unsplash

本周主题:给自己立个 flag

上周五(09/03)的周记跳过了,原因是周四周五两天在忙 day of code,一个公司内部的发明比赛。比赛的结果是我们组与另一组并列第一,都得到16票。奖品是 100 * 2 圆京东礼品卡。作为第一名,我们还要参加下周三(9/16)展开的全球竞赛,与其他地区的小组展开 PK。

下周的比赛下周再说,我先说说上周的比赛,以及,我要立一个什么 flag。

比赛的技术环节,我个人觉得与前几届没有什么太大的进步,但是参与者的演讲能力,相比之前真的进步太多了。我正好协助本组负责演讲的同事准备材料,因此了解到一些他们的做事办法。相比工程师们更加重视发明的技术性,这次的演讲者们更加专注于如何讲好故事。比如,遇到了什么问题,如何分析问题,提出发明,以及设计产品。他们非常看重提出解决方案之前的梳理归纳,力求思维的过程足够顺畅合理,逻辑自洽。从我个人的感受来说,这样的叙事方式更符合人的预期。先让你充分的理解为什么,再理解做什么,最后如何做。从现场的反响来说,这样的讲法效果非常好,充分了调动观众的主动性,现场一度掌声雷动。

这次经历触动了我,我也有很多想法,虽然没有精力将他们全部变成产品, 但是可以先讲故事啊。我觉得讲故事这件事情起码有两个好处,一个好处是,锻炼自己的思维能力。另外一个是,也许讲着讲着,就发现很多想法其实并不好。

所以我要立一个 flag,从本周开始,我要学着用这样的逻辑来拆解一个个 idea,可以是一个独立的产品,或者对现有产品的改进。

读书

不知道你们有没有读过原著,或者看过电影。如果有的话,那么,你们讨厌德拉科 马尔福吗?你们有没有盼望着,马尔福最后终于死了,整个世界都清净了。如果你真的盼望过,到最后,你肯定会有些失望,因为jk罗琳并没有把这样一个大家恨得牙痒痒的角色写死,他不仅没有死,而且结了婚,有了孩子。

我跟妻子讨论《哈利波特》与普通爽文的区别,我认为,最大的区别就是,《哈利波特》会让你觉得,真实的人生是什么样的体验。这个观点可能有些奇怪,《哈利波特》虚构了一个魔法世界,那里的巫师,可以坐着扫帚满天飞,可以用变形术将茶杯变成老鼠,或者反过来。无论怎么看,这都不是现实世界的体验。

darshan-patel-jAThVtHa34A-unsplash Photo by Darshan Patel on Unsplash

可我指的并不是这些。

《哈利波特》里有很多坏人,马尔福,乌姆里奇,魔法部部长福吉,在哈利和他的朋友的视角里,这些人都是讨厌鬼,如果你将身份带入十几岁的哈利身上,你很容易就会有同样的想法。

但是当你将视野放大一点,放到霍格沃兹之外,你会发现,这些都算不得什么。与伏地魔以及他忠实的食死徒们相比,马尔福们的罪恶不值一提。你讨厌马尔福,马尔福也讨厌你,但这不代表你们就要杀死对方。

推及到生活中,从小到大,谁没遇到过几个讨厌的家伙呢?上学时总是跟你作对的同学,上班时总是给你难堪的同事,势利的亲戚,难缠的邻居,这些都让你抓狂。可是生活就是这个样子,你总会遇到自己躲不掉的马尔福,这很糟糕。

但是,同时,你也会遇到自己的罗恩,赫敏,海格,秋张,可爱的韦斯莱夫人,调皮的韦斯莱双胞胎。这是你的幸运。

这就是真实的人生体验,不会一直幸运,也不会一直倒霉。虽然是魔法世界里发生过的事情,但仍旧让人感觉亲切。这是 jk罗琳的伟大之处,也是所有传世作家的伟大之处。祝贺所有爱过《哈利波特》系列的人,你们很幸运。

健身

体重 - 0.0 kg 这两周的力量训练比较多,原因在于,我认为自己的上肢力量太薄弱了,尤其是前臂,正在学习科学的锻炼。

另外,这也是本周记最后一次记录健身,从下周开始,将会用独立的文章来记录健身。取得阶段性成果,或者解决了有意思的问题,才会单独输出。这样比较有意义。因为锻炼身体本来就是见效很慢的事情。至于打卡,也许未来会使用一些打卡软件,做做记录。但是目前还没有这样的想法。

App

这两周值得记录的软件是 Notion,一款笔记软件。Notion 能做的事情很多。对我来说,它的优点有:

  1. 简单的笔记组织方式
  2. 编辑器简单实用,排版优美
  3. 符合直觉的定制方式,比如各种图标,文章顶部图片,简单的点击就能进入定制模式。
  4. 同步迅速

可以预期在很长一段时间我会用 Notion 来:

比如,child 是一个 select,它自己包含了逻辑来控制 selected value。同时,外面有一个 parent,parent 可能会相应global 的消息,比如 url change,然后重置 child 里面的 selected value。

通常是怎么实现这种逻辑的呢?以 React Hooks 举例,我们需要在 child 里面有一个 useEffect,监听 parent 传过来的 value,如果 value 是合法的,就使用对应的 setter 修改 selected value。

class 时代的 React 也是这样的思路,简单来说,就是必须有一个机制来通知 child ,parent 传过来的 props 变化了,child 才能有机会选择做些什么。

function Child({ nextValue, options }) {
  const [value, setValue] = useState(nextValue ?? options[0]);
  const handleChange = useCallback((e) => {
    setValue(e.target.value);
  }, []);
  useEffect(() => {
    setValue(nextValue);
  }, [nextValue]);
  return (
    <>
    <h2>Child</h2>
    <select value={value} onChange={handleChange}>
      {options.map((o) => (
        <option key={o} value={o}>{o}</option>
      ))}
    </select>
    </>
  );
}

function Parent() {
  const options = useMemo(() => ["a", "b", "c"], []);
  const [value, setValue] = useState(options[0]);
  const handleChange = useCallback((e) => {
    setValue(e.target.value);
  }, []);
  return (
    <div>
      <h1>Parent</h1>
      <select value={value} onChange={handleChange}>
        {options.map(o => <option value={o}>{o}</option>)}
      </select>
      <Child nextValue={value} options={options} />
    </div>
  );
}

上面这种做法在编程上证明是可行的。如果你不理解为什么 defaultValue 的变动应该起到重置 child 的作用,可以听听我的解释。在解释之前,让我给他改个名字,不叫 defaultValue,叫做 nextValue。nextValue 的作用定义为,下一次 render 时,child 应该变迁到这个状态。这样的定义下,nextValue 重置 child 的作用就不会像 defaultValue 那么违和。

除了改变命名这种欺骗自己的办法,还可以尝试重新划分 component 职责。我们可以看到 child 其实融合了业务逻辑和视图,我们可以将 child 做成纯视图,业务逻辑上升到 parent。由 parent 决定 child 的 value。

function Child({ options, value, onChange }) {

  return (
    <>
    <h2>Child</h2>
    <select value={value} onChange={onChange}>
      {options.map((o) => (
        <option key={o} value={o}>{o}</option>
      ))}
    </select>
    </>
  );
}

function Parent() {
  const options = useMemo(() => ["a", "b", "c"], []);
  const [value, setValue] = useState(options[0]);
  const [next, setNext] = useState(value)
  useEffect(() => {
    setNext(value)
  }, [value])
  return (
    <div>
      <h1>Parent</h1>
      <select value={value} onChange={e => setValue(e.target.value)}>
        {options.map(o => <option value={o}>{o}</option>)}
      </select>
      <Child value={next} onChange={e => setNext(e.target.value)} options={options} />
    </div>
  );
}

javascript 没有 swift 那样的 property observer 机制,否则可以实现的更加优雅,像这样:

let value: String {
  didSet {
     next = value
  }
}