개요

벌써 좀 오래전 일이긴 하나, 경험의 기록 차원에서 남겨 둔다.

진행 환경

  • : 기획을 주도하는 사람 한명을 중심으로, 전부 완전히 수평적인 관계의 5명 (나이도 비슷).
  • 프로젝트: 대략적인 방향에 대해서만 동의된 상황에서 1년간 진행.
  • 상황: 프로젝트 성공 여부에 따라서, 인사 평가가 결정.

진행

초기

  • 프로젝트 진행방향을 구체화하는 과정에서, 서로 의견충돌이 발생.
  • 의사결정권자가 없으므로, 의견충돌이 중재되기 힘듦.
  • 어느 정도 서로 감정을 건드리는 상황도 종종 발생.

중기

  • 서로 의견충돌이 발생할 만한 종류의 이야기는 언급을 피함. 그러다 보니, 중요한 의사결정이 제대로 내려지지 않음.
  • 기획방향에 동의하지 않는 사람은 업무에 적극적으로 참여하지 않음.
  • 생산성에 비효율이 발생.

말기

  • 프로젝트 결과물이 기대에 미치지 못함.

요약

  • 책임과 권한이 비슷한 여러사람이 이끄는 조직을 성공시키는 것은 쉽지않다. 이것이 일한사람이 이끄는 조직보다 더 나은지 아닌지는 모르겠으나, 고려해야할 사항이 좀더 많아 보인다.
  • 한명이 의사결정권(책임과 권한)을 가지는 형태의 조직이 일반적으로 사용되는 것은 이러한 경험의 축적에서 비롯된 것으로 생각된다.

Test environment: Node 12.18.2 on Intel(R) Xeon(R) CPU E5-2697 v3 @ 2.60GHz


const SZ = 99999999


const l2a = [];
for (let i = 0; i < 10000; i++) {
    const sub = [];
    for (let j = 0; j < 10000; j++) {
        sub.push(j);
    }
    l2a.push(sub);
}

let s = new Set();
let t = -Date.now();
for (const a of l2a) {
    for (const n of a) {
        s.add(n);
    }
}
t += Date.now();
console.log('Takes: ', t);

const ta = [];
t = -Date.now();
for (const a of l2a) {
    ta.concat(...a);
}
s = new Set(ta);
t += Date.now();
console.log('Takes: ', t);

Result is

Takes:  3070
Takes:  1665

Concating and expanding array are very fast comparing to calling a function(Set.add).

NOTE: I observed it rxjs 5.5.12, 6.5.4, 6.5.5.

You may think that below two codes gives same results where s0 and s1 are instances of BehaviorSubject.

Code-1

s1.pipe(
    withLatestFrom(s0)
).subscribe(([v1, v0]) => {
    console.log(v0, v1);
});

Code-2

s1.subscribe(v1 => {
    s0.pipe(take(1)).subscribe(v0 => {
        console.log(v0, v1);
    });
});

In general case, it's true. But, in very unique situation, these gives different results.
Here is test code for it.

const s0 = new BehaviorSubject('A');
const s1 = new BehaviorSubject('a');

setTimeout(() => s0.next('B'), 500);

let i = 0;
s0.pipe( /* Part-A */
    withLatestFrom(s1)
).subscribe(([v0, v1]) => {
    console.log('s0-pipe: ', v0, v1);
    s1.next(++i);
});

s1.pipe(
    withLatestFrom(s0)
).subscribe(([v1, v0]) => {
    console.log('s1-pipe: ', v0, v1);
});

s1.subscribe(v1 => {
    s0.pipe(take(1)).subscribe(v0 => {
        console.log('s1-sub: ', v0, v1);
    });
});

This gives following result.

s0-pipe:  A a
s1-pipe:  A 1
s1-sub:  A 1
s0-pipe:  B 1
s1-pipe:  A 2  <=
s1-sub:  B 2

Two very interesting results are observed. s1-pipe: A a and s1-sub: A a are not shown. And s0 value at second s1-pipe is not latest one!

To avoid this, I used below workaround at code Part-A.

s0.pipe(
    withLatestFrom(s1)
).subscribe(([v0, v1]) => {
    console.log('s0-pipe: ', v0, v1);
    setTimeout(() => s1.next(++i));
});

Then, it gives

s0-pipe:  A a
s1-pipe:  A a  <=
s1-sub:  A a  <=
s1-pipe:  A 1
s1-sub:  A 1
s0-pipe:  B 1
s1-pipe:  B 2  <=
s1-sub:  B 2

I think it's design of rxjs. One thing I can learn from above is that it's very risky using circular withLatestFrom at rxjs.

+ Recent posts