更新日:
投稿日:

『医師残業規制の9割「守れず」』という記事が神戸新聞紙面にあり、これを読んだ感想だ。

まず女性は男性になれないし、その逆もしかり、要するに男女情動など土台無理であるという話。

この記事には『長時間労働は女性のキャリア形成を阻んできたとの指摘もあり是正が急務』とあり、また『本来は勤務とすべき業務を「自己研さん」とするケースは多いとされ』ともある。

ソースは失念したのだがキャリア形成においては労働時間が多いほど有利であるという文献を見たことがある。これは当たり前のことで、例えば、労働時間が4時間の人と8時間の人では単純に経験値が倍違う。

一般的に女性は身体上の制約などにより男性より労働時間が短い傾向があるとされている。バリキャリ女性は別として、深夜残業やサービス残業をいとわないのは一般的に男性だろうし、勉強会といった自己研鑽のイベントも圧倒的に男性が多い。

思うに昨今言われる男女差別の一つは男性が頑張りすぎるせいで女性が活躍できない現象のことを指しているのではないかと思う。どちらかというとそれは差別ではなく、どうしようもないことである。

車いすの人が健常者に二足歩行できるのは卑怯だ、差別だ、というようなもので、どうにもならないことだ。そこに対し階段を全廃し、すべてスロープかエレベーターにしろというのが女性の言い分に近いだろう。

そもそもなぜ女性を活躍させないといけないのか?差別だから?少子化で人がいないから?少なくとも女性が働けば働くほど少子化が進むため後者は嘘である。

男性と比べた場合に女性の待遇が低いというのも嘘だ。バリキャリ女性や女医、イラストレーターなど、高位の地位についている女性は少なからず存在する。いわば名誉男性とされる女性の存在だ。男性と同じか、それを超える能力が女性にあれば、ちゃんとそれは優遇される。

しかし今時流のテックカンパニーを見てみよう。GoogleもAmazonもAppleもMicrosoftもMetaも創業者は男性だ。別に女性が創業者になってはいけない法律などなかったはずだ。これがどういうことかというと、差別というより単に女性にその才能がないだけの話だけなのだ。これは事実であり、差別ではない。

仮に男性が女性より有能とした場合、これは差別ではないし、逆に男性の有能さを潰すほうがおかしいと思う。そんなことをしたら世の中は無能であふれ、まさに共産主義になってしまうだろう。共産主義ではすべてが平等だ。

私はこのままではいけないと思う。女性を差別するのではなく、女性の強みを生かせる社会が必要に思う。少なくとも資本主義になる前の日本では女性は立派な労働者の一つだった。キャリアこそなかったが女工として働き続けることができていたはずだ。

キャリアさえなければ妊娠や出産で働けない期間があっても問題にはならない。別に女工でなくともイラストレーターや作家もそうだろう。女性のクリエイターには非常に魅力的な作品を作る人も少なくない。少なくとも日本では清少納言のころからそうだろう。

そこを考え直していくのが本当の働き方改革ではないだろうか?私はそう思う。

このままでは少子化はますます加速し、人類は衰退するだろう。残念なことに子供が増えている世界というのは人権もへったくれもない第三世界の話だ。そこに戻ろうというわけではないが、結局のところ昭和に戻らないとどうにもならない気はする。

因みに男性が女性より労働を頑張ることを「Greedy work」というらしい。

投稿日:

飲み会というと嫌なイメージがある人も少なくないだろう。実際私も好きではない。しかし飲み会に出ることにはメリットもあるので、デメリットと合わせて紹介していく。

まずメリットからだが、飲み会には役員や偉い人、普段会わない他の部署の人がいるので、参加することで顔を売ったり、知らなかった情報を得たり、交換することができる。特に技術者は来たがらない傾向があるので、来るだけでアドみたいなところがある。実際着てるのは飲み会が好きな人間か、したたかな人間のどちらかだろう。私は後者だ。

次にデメリットだが、飲み会と言うのは大声で話したり、取り箸無しで回し食いすることが多々あるし、飛沫も飛び交いまくる。唾液には様々な菌やウイルスが潜んでいるのでこれを食べたり吸ったりすることで何かしらの感染症にかかる。新型コロナで自粛が呼ばれたのは記憶に新しいが、感染するのは新型コロナに限らない。

一番ヤバイのは虫歯菌だ。実は人間産まれたときは虫歯菌を持っていない。おおよそ3歳までに口移しなどで親から移るとされているが、極めて稀に保菌していないケースがある。少なくとも私は成人するまでに虫歯になったことはなかった。子供の頃は歯磨きなどしない日の方が多いという酷い生活だったのにも関わらずだ。

私は人生初の飲み会に参加したわずか半年後に虫歯を発症した。この時を境に歯磨きを良くするようになった。いやまぁマナーとしてするのが当たり前なのだが…。それまでは虫歯にならないのでしていなかった。

感染症以外の観点だとどうしても会話の声量を張上げないと声が相手に聞こえないので喉をやられがちだ。一回の飲み会ではなんともないだろうが、連日となれば喉が焼け、そこから風邪になるというのは容易にある。少なくとも私はそうだ。

そこを受容してまで参加するメリットがあるかだが、そこは個々の状況によって変わり得るだろう。私はつまらん説教みたいなのでも一見の価値はあると思っているし、パワハラ上司とのサシ飲みでも行く方だ。その方が人間関係も円滑になる。

昔は部屋の隅でだんまりしてたり、上司が財布を忘れたので何故か私が払ったりとかろくな目にあっていなかったが、最近では多少は話せるようになり、損得勘定もできるようになった気はしているので成長したように思う。結果としてはデメリットがメリットを上回るので参加している形だ。

投稿日:

今回はサイトトップが、ひとまずの理想形になったので、その成果発表をしていく。

このページは2023/04/06に重い腰を上げてBioサイトを作ったで作成したが、そこから先でも思い立った時にちまちまメンテし続けていた。

ひとまず、前回の記事と今回を比較していく。

まず、ビジュアル面では、ずっと入れたかった指紋情報を書くことができた。最初は公開鍵を何とか書こうとしていたのだが、ダイアログやアコーディオン的なものは使いたくなかったし、JSも使いたくなかったので、短く収められる指紋で妥協した。

次にアイコンサイズの統一だ。以前はブログ、YAMAP、はてブのアイコンサイズが異なっていて統一感がなかったが、これを揃えることで統一感を出すことができた。代償としてブログの存在感が薄くなってしまったので、これはどうにかしたい気もする。

またRootsの表示が他の要素と微妙に異なっており、ズレている問題があったが、これも直した。直したらスマホ表示時に途中で折れるようになってしまったのでフォントサイズを落とした。この部分はほかにもSSIを使って更新日時を表示したり、コピーライトの最新年もSSIで動的に吐くようにしていたり、地味に工夫している。アクセスカウンターもaltにカウント値と様相を出すようにして、もし画像が見れなくとも読み取れるようにしている。恐らくアクセスカウンターのAltにカウント値をSSIで入れる試みはなかなか珍しく、ひょっとしたら私くらいしかやっていないのではなかろうか?

前回 今回
前回のやつ
今回のやつ

ビジュアル面以外ではページサイズの削減やCSSの見直しをしている。ページサイズの削減ではfontawesomeのCSSを外しSVGを直接埋めることで大幅に容量を落としているほか、GZIP転送を利用してページサイズを圧縮している。CSSの見直しはDOM階層構造でしていた部分を個別のクラスに分けて保守性を高めている。DOM構造に依存していると意図しない部分にCSSが当たって崩れることもあり、あまりよくなかった。とはいえ、全部消したわけではなく、支障がない場所はそのまま残しているので臨機応変にやっている。

以下はそれぞれ、SP/PCでの前回と今回のパフォーマンス比較だ。SPはFirst Contentful Paintが1.4秒から0.9秒に、Largest Contentful Paintが1.4秒から1.0秒に減っており、PCもSPはFirst Contentful Paintが0.4秒から0.3秒に、Largest Contentful Paintが1.0秒から0.6秒に減っており、大きな効果が出ていることがわかる。パフォーマンスも99だったSPが100に上がったので十分だろう。全体スコアもPCはオール100、SPもSEO以外は100なので十分といえる。SPのSEOを改善する気は今のところないので、これでFixにする。

以前のSPビューでの結果 今回のSPビューでの結果
以前のSPビューでのLighthouseの結果
今回のSPビューでのLighthouseの結果
以前のPCビューでの結果 今回のPCビューでの結果
以前のPCビューでのLighthouseの結果
今回のPCビューでのLighthouseの結果

しかし、HTTPSに対応しており、レスポンシブデザインであるにも関わらず、CGIによるアクセスカウンターとSSIによる動的生成を使っていて、どこにもJavaScriptが書かれていないサイトというのは、そうそうないと思うので、今時珍しいサイトとしてネタにしていきたいところだ。何ならHugoのような静的ジェネレータも使っていない手書きのHTMLである。全て私が丹精を込めてキーボードを打鍵して作っている。当たり前だがChatGPTやCodeCopilotをはじめとしたAIも使っていない。

Google Search Consoleで状況を確認してみることにする。(Google Analyticsやレンサバのログ解析も似たような結果になっている)

クリック数は落ちているがクリックレートは維持されていることが読み取れる

アクセス数は以前よりかなり落ちている。これはタイミングの問題かもしれない。もし、CMS変更が原因であれば、URL変更やHTMLの構造変更が影響しているのだろう。少なくともコンテンツは丸ごと移してるし、URLのリダイレクトもほとんどは機能しているはずだ。いや実際に機能しているかまで確認はしてないが…。

まぁアクセスが多くても負荷が高まってサーバーが落ちたりするので、このくらいが程よいのかもしれない。

未登録URLが増え、登録済みURLも増えたことが読み取れる

またインデックスについては未登録URLがグッと増えた。グラフを見る感じWordPressのURLがまるっと未登録になり、adiaryの分が増えた感じだろう。adiaryの方が記事URLに対してサイトマップの登録率が高いが、これはadiaryとWordPressでサイトマップのファイル構成が異なることに起因している可能性がある。例えばadiaryはサイトマップが1ファイルなのに対し、WordPressは複数ファイルであるため、Google側の解釈に差が出ているとか、そもそもXMLの内容も違うはずなので、色々影響しているのかもしれない。

インデックス状況についてはWordPressの頃は手動登録しないとインデックスされないことが少なくなかったが、adiaryでは何もせずともインデックスされるので、ここについては大きく満足している。やはりこれはWordPressよりadiaryの方が早いことに起因しているだろう。

更新日:
投稿日:

親クラスをモックして子クラスの単体テストをしたいときに

確認環境

Env Ver
@swc/cli 0.1.65
@swc/core 1.3.105
@swc/jest 0.2.31
@types/jest 29.5.11
jest 29.7.0
typescript 5.3.3

サンプルコード

コードのフルセットは以下
https://github.com/Lycolia/typescript-code-examples/tree/main/mocking-base-class-with-extension-class-swc-ts

ディレクトリ構成

src
 ├─BaseClass
 │  └─index.ts
 └─ChildrenClass
    ├─index.ts
    └─index.spec.ts

src/BaseClass/index.ts

親クラス。この例は抽象クラスだが別に具象クラスでも何でもいいと思う

export abstract class BaseClass {
  constructor(
    private baseValue: string,
    private ctx: { [key: string]: unknown }
  ) {}

  public hoge<ResultT>(payload: { [key: string]: unknown }) {
    // テスト走行時には全て無効な値を流し込むため
    // それらの影響で落ちないことの確認のために、オブジェクトの子を意図的に書いている
    console.log(this.baseValue, this.ctx.hoge, payload.piyo);
    // サンプルコードなので戻り値はスタブ
    return {} as ResultT;
  }
}

src/ChildrenClass/index.ts

子クラス

import { BaseClass } from '../BaseClass';

export class ChildrenClass extends BaseClass {
  constructor(baseValue: string, ctx: { [key: string]: unknown }) {
    super(baseValue, ctx);
  }

  public piyo<ResultT>(payload: { [key: string]: unknown }) {
    try {
      // このsuper.hoge()をモックして、
      // catchの中に流れるかどうかを確認するのが目的
      return super.hoge<ResultT>(payload);
    } catch (err) {
      // 実際はロガーが動くような部分だが、サンプルコードのためconsole.logで代用する
      console.log(err);

      throw err;
    }
  }
}

src/ChildrenClass/index.spec.ts

子クラスのテスト

import { ChildrenClass } from '.';
import { BaseClass } from '../BaseClass';

describe('fetch', () => {
  it('親のfetchが呼ばれ、親の戻り値が返ってくること', () => {
    // 子が正しくreturnしてくるかどうかを確認するための値
    const expected = { code: 200 };

    // Class.prototypeとやるとモック出来る
    const spiedSuperFetch = jest
      .spyOn(BaseClass.prototype, 'hoge')
      .mockReturnValue(expected);

    // 親クラスの処理はモックするので適当な値を入れておく
    // この内容が実行されていればテストが落ちるのでテストコードが間違っていることの検証に使える
    const inst = new ChildrenClass('aaaa', {} as { [key: string]: unknown });
    const actual = inst.piyo({ foo: 123 });

    // 親クラスのメソッドが正しい引数で呼ばれたことの確認
    expect(spiedSuperFetch).toHaveBeenCalledWith({ foo: 123 });
    // 子クラスのメソッドの戻り値が正しいことの確認
    expect(actual).toStrictEqual(expected);
  });

  it('親のfetchで例外が出たときに、ログ出力とリスローがされること', () => {
    const expected = Error('ERR');
    // 親クラスのメソッドが例外をスローするケースを作る
    jest.spyOn(BaseClass.prototype, 'hoge').mockImplementation(() => {
      throw expected;
    });

    // catch句の中でロガーが動いているかどうかの検査用
    const spiedConsoleLog = jest.spyOn(console, 'log');

    const inst = new ChildrenClass('aaaa', {} as { [key: string]: unknown });

    // 例外がリスローされていることを確認
    expect(() => {
      inst.piyo({ foo: 123 });
    }).toThrow(expected);
    // ロガーが動いていることを確認
    expect(spiedConsoleLog).toHaveBeenCalled();
  });
});