Runner in the High

技術のことをかくこころみ

マネジメントする立場になって思うこと

今年の夏頃から会社で4-5人チームのリーダーをやっている。

新卒で入社したころはまさか自分がリーダー的存在になるなんて思っても見なかったが、やってみるとこれはこれでおもしろい。来年になる頃には自分がなんでこの選択をしたのか忘れてしまいそうな気がするので、ここに書き残しておく。

やってみようと思った理由

正直なところ、学生時代から「やっぱエンジニアはコード書いてナンボ」みたいな気持ちでいて、当初はリーダーだとかそういうものには微塵も興味がなかった。Twitterとかを見ていても「マネジメント層になるとコードが書けなくなる」みたいな話もちらほら目にしたり、そういうものを見ると尚更「そんなんやるもんじゃねーな...」と思っていた。

しかし、実際チームでマネジメントをしている人をみている限りでは、マネジメントをしているからコードが書けないだとかそんなことはないどころか、ビジネス的な視点とエンジニアリングの視点がいい具合に混ざり合って、大局的に物事が見えているようにも見えた。そのような事実を目にすると、少しづつ自分の中で「自分が目指すキャリアというのはこれなんじゃないか?」という気持ちが高まってきた。

加えて、社外の人々の話を聞くところでは、国内のベンチャー(メガベンチャー、ミドルベンチャークラス)ではどの企業においてもプロジェクトをマネジメントする層が絶対的に足りていないという話を非常によく聞いた。眉唾ではあるが、聞くところによればいまのベンチャー界隈におけるマネジメント層は年齢的に20代後半から30代前半であることが多く、この世代はサブプライムローン危機による就職の難しさやライブドア・ショックでIT企業に対する良くない印象がついた時期でもあったため、そもそもソフトウェア産業に携わる人間の絶対数が窪んでいるのではないかという話である(要出典)

なるほど、そういうことであればなおさらマネジメントをやったほうがいい。人がやりたがらないことをやることで自分の価値が上がる。そんな理由でマネジメント・キャリアに進んでみることにした。

マネジメントをするエンジニア

マネジメントをするようになったとはいえ普通にコードは書くし、いまだに機能開発のコーディング作業が1日の大半を占める。この部分は以前とあまり変わらないところだと思う。逆に、自分の中で大きく変化があったのは、自分のチーム以外の状況を今まで以上に意識するタイミングが増えたことか。

自分の開発しているプロダクトでは自分のチーム以外にもいくつかのチームが存在している。ビジネスサイドのロードマップだったり開発進捗は毎日変化するため、常に状況を鑑みて他チームのリーダーを話し合いチームリソースの配分であったりリスケジュールを行うことになる。この種の意思決定をするには、チームの開発進捗だけではなく他チームとのリソース調整を考えたり、ビジネスサイドの動きをみつつスケジュールを考え直したり、これはかつてのように1プレイヤーとしてただコードを書くだけでではあまり意識できないところだと感じた。

逆に言えば、一度こういう視点を身につけると今度はメンバとして働く上でも強い。仮に自分がリーダーではないとしても、リーダー的な視点を持って意見や提案をできる。これはやってみないと分からないところだと思う。

マネジメントのおもしろさ

今の会社だからというのもあるかもしれないが、やはりマネジメントは「自分でコントロールしている感」がすごくあり、これはめちゃくちゃにおもしろい。もちろんその分責任も大きいが、自分の意思決定がビジネスにインパクトを与えるというのはまた一味違ったおもしろさがある。

マネジメントというと様々な重圧がありそうな雰囲気もあるが、個人的にはいまが一番多くの人に頼れているようなそんな気がしている。チームのメンバ、ほかチームのリーダー、上長、などなど、1メンバとしてチームで開発をしているとき以上に自分が関わるネットワークが大きくなり繋がるノードが増えたような、そんな感じ。

組織パターン

組織パターン

BtoBなソフトウェア開発における必読書3選

BtoBなソフトウェアの開発において業務知識なしにシステム設計をすることはほぼ不可能に近い。

これまで、業務支援系のシステム開発SIer企業たちのお家芸であったが、近年ではWeb系のベンチャー企業やスタートアップであってもこれまでSIerが担っていたようなドメイン領域で戦うことが増えている。

「会計処理」「流通管理」「在庫管理」「人事管理」あたりのドメインにまつわるシステム設計は、BtoBをやっていればいつか必ず遭遇することになる。その際にドメインに関する知識を一切持たずにまともなシステム設計をすることはたいていの場合難しい。

Web系であれなんであれ、BtoBなソフトウェアエンジニアは自分たちが取り組むドメインに関する知識を持ってシステム設計に臨む必要がある。これはデザインパターンや設計手法"以前"の話だ。

ITエンジニアのための「業務知識」がわかる本

財務会計」「販売管理」「物流・在庫管理」など、様々な企業活動の業務知識を集約した一冊。これを読むだけで、ざっくり世の中の企業が日ごろから行っている業務ドメインの活動やそれに関連する法律などを知ることができる。また、各業務ドメインを扱うエンタープライズ系システムにおいてどのような機能が必要とされるか、なども例として紹介されており非常に参考になる。

どちらかといえばこの本は業務のライフサイクルやそれに絡むプロセス、用語などを網羅した本になっている。なので、この本を読んだ上で更に自分が深めたいドメインに特化した書籍に向かうのがよい。その手掛かりをこの本は十分に提供してくれる。

データモデル大全

「データモデル大全」は上の本で学ぶような業務知識をどのようにしてデータモデルに落とし込むべきかが学べる良書。特にエンタープライズ系システムが扱うドメインをテーマとして積極的にカバーしており、具体的には「受注と出荷」「サービスと契約」「在庫」などが含まれる。

ソフトウェアエンジニアである我々は、業務知識を実際のソフトウェアに落としこむにあたってデータモデリングを必ずすることになる。データベース・ミドルウェアを使わないソフトウェアはほとんどないと言っても差し支えない。とくに、在庫管理のデータモデル設計の考え方はECサイトや在庫管理システムを作ることがなくても間違いなく学びになる。

これまでのDB設計で「残り〇〇」のようなデータをDB上の1カラムにステートソーシングで表現してきた人は間違いなく設計の観点がレベルアップするだろう。

システム設計のセオリー

システム設計のセオリー --ユーザー要求を正しく実装へつなぐ

システム設計のセオリー --ユーザー要求を正しく実装へつなぐ

  • 作者:赤 俊哉
  • 発売日: 2016/02/26
  • メディア: 単行本(ソフトカバー)

「システム設計のセオリー」はいわゆる「エンタープライズ系システム」の開発における開発プロセスにおいて、それぞれのプロセスの目的や手法、注意点などを説明している。大規模なソフトウェアの開発プロセスにおいて「どのような観点で仕様を決めるべきか」「どのようなフォーマットで仕様をドキュメントに残すべきか」などを大局的に学べる一冊。*1

アジャイル開発の登場によって、特に新興のWeb系企業でウォーターフォール開発が「時代遅れ」かのように言われがちだが、それがウォーターフォール開発を無視してよい理由にはならない。

どんなソフトウェアの開発にも必ず「要求分析」「要求定義」「外部設計」「内部設計」などのフローが暗黙的に存在しており、それぞれの役割を知って初めて自分たちの開発に特化したプロセスの取捨選択ができる。深く考えずに「ドキュメントは大事じゃないから残さなくていい」「テストはなんとなく画面を触っとけばOKだろう」などの意識でいる人ほど、改めてウォーターフォールに立ち返るべきだ。

izumisy.work

*1:この本に関してはBtoBに限ったはなしではないが、いわゆる基幹系システムの開発という文脈で取り上げてみた。

GPD PocketからOneMix3 Proに乗り換えた

かつてIndiegogoでバックしたGPD Pocket初代をときたま外出のとき持ち歩いたりしていたが、とうとうOneMix3 Proに乗り換えた。

性能も使いやすさも段違いになった。

izumisy.work

今の世の中のUMPC全体のトレンドが7型から8型台へ移りつつあり、OneMix 3シリーズに限らずMAG1やGPD Pocket P2 Maxなどもまた8インチモデル。

これはすごく理に適っているなと個人的には感じていて、なにより7型は正直キーボードがめちゃくちゃきつい。 GPD Pocketを買った最初のころは、見た目が好みというだけでキーボード入力を頑張っていたが、手の小さい自分ですらやはり7型だとタイプミスがかなり頻繁に起こる。

7インチは見た目こそ小さくてかわいいが、実際に使うとなるとキーボード入力の難しさがめちゃくちゃネックになってくる。

f:id:IzumiSy:20200919211958j:plain
左がGPD Pocketで右がOneMix3 Pro

しかしOneMix3 Proのような8インチ台に突入してくると圧倒的にキーピッチに余裕がでる。 OneMix3 Pro特有の部分で言うならばやはりスペースキーだけが若干遠くアクセスしずらいという点はあるものの、それ以外でキーボードに対する不自由さはほとんどない。 このキーボード配列は確実にUMPCを日ごろから触る人が設計している。

Windows10からはWSLも使えるので、Ubuntuデュアルブートにしなくても開発環境が整うのもうれしいところ。 Web開発をするにはやはりMac/Linuxじゃないと、という思い込みがあったが、近年のWSLの進歩を見るとWindowsだけでほぼ開発を完結させられそうな未来が見える。

ちなみにモバイルディスプレイはJapanNextの10inchのやつがコンパクト&超軽量でおすすめ。

isucon10に出て予選敗退した

iguchi1124hayashikunとisucon10に出た。一番伸びたスコアは1300くらい。

f:id:IzumiSy:20200913175854p:plain

やったこと

覚えていることベースでやったことを書いてみる。

自分が覚えているのは基本アプリケーションサイドの変更ばっかり。

マシン構成の変更

hayashikunとiguchi1124がAP2台+DB1台の構成に変更した。

index張り

使われてそうなとこにいくつか張った

create index char_stock on isuumo.chair (stock);
create index estate_latitude_longitude on isuumo.estate (latitude, longitude);
create index estate_height_width on isuumo.estate (door_height, door_width);
create index estate_rent on isuumo.estate (rent);

nginxでクライアントキャッシュ

hayashikunが椅子と物件の詳細情報をクライアントサイドキャッシュするようにした。効果は不明。

よく考えたら椅子は在庫数みたいなデータがあるのでキャッシュさせたらまずそうだがスコアには影響はなかった。

なぞって検索の処理をAPサーバでやらせる

ポリゴンの内外判定系をSQLでN+1してやっているということがわかったのでpolyclip-goというライブラリを使ってST系関数の呼び出し部分をアプリケーションサイドに寄せた。

スコアは10くらい伸びた気がする。

LowPriced系のオンメモリキャッシュ

APサーバで結果をキャッシュするようにした。これはめちゃくちゃ効いて400くらい伸びた。

DBのアプリケーションの最大コネクション数を変更

10→50にしてみた。効果があったのかは不明。

botリクエストの排除

UAを見てbotだったら503返すようにするあれ。効果は不明。

ランキング処理

任意の椅子にあう部屋を取得するエンドポイントで使われているSQLがorを5つ使っているのでそのぶぶんのorをひとつに。

椅子の縦横奥行きのうち最長辺を除いた二辺でドアの縦横幅と比較すればorをひとつにできた。

   var estates []Estate
    w := chair.Width
    h := chair.Height
    d := chair.Depth

    // 短い短辺ふたつをとりだす
    lengths := []int64{w, h, d}
    sort.Slice(lengths, func(i, j int) bool { return lengths[i] < lengths[j] })
    len1 := lengths[0]
    len2 := lengths[1]

    query = `
        select *
        from estate
        where (door_width > ? and door_height > ?)
            or (door_width > ? and door_height > ?)
        ORDER BY popularity DESC, id ASC
        LIMIT ?
    `
    err = db.Select(&estates, query, len1, len2, len2, len1, Limit)

featureテーブル

これはやろうとしてできなかった。

LIKEを発行してchairとestateのfeaturesカラムを舐めているクエリがいくつかあったので、それに目星をつけてchairとestate用のfeatureテーブルを別で用意してみることに。これがうまくいけば検索クエリが改善するので購入ボリュームが底上げされると思っていた。

しかし、実際にはLIKEを発行するようなクエリは全体でみるとほんの数パーくらいしか占めておらず、改善する意味はほとんどがほとんどないということが終わってから分かる。また、意味がない割にfeatureテーブルを作ろうとするとめちゃくちゃ難しく、後半はここで時間をかなり使ってしまった。

思ったこと

用意されているDBテーブルがふたつだけ、そしてアプリケーション実装コードも短く、いままで以上にシンプルな構成のアプリケーション、という感じだった。

ベンチを動かしてみると一番負荷が集中するのは結局DBで、いかにキャッシュを効かせてDBへのアクセスを減らすか、いかにDB設計を考えて負荷を分割するか、という部分がポイントだったのかなという印象。しかし我々のチームはDBの分割などの戦略までは到達できなかったので、上位のチームがどのようなDB構成の戦略をとっていたのかが気になる。

また、今回のアプリケーションisuumoの特徴として

  • レコードの入稿がCSVを用いたバルクで行われる&頻度少なめ
  • 物件テーブルには更新がない(ユーザーの行動も資料請求で終わる)
  • 検索クエリが極めて複雑

など、実際のsuumoのようなプロダクトにものすごく近い状況が再現されており、おそらくベンチマーカーの挙動も 検索→商品詳細閲覧→資料請求or購入 という流れをたどるように作られていたように思える。つまり、パーチェスファネルのようにまずは検索部分のボリュームを稼がないとスコアに直接響く資料請求や購入につながらない、という感じ。

なので、早い段階で検索より先の部分(商品詳細とか購入とか)を改善しても、結局検索部分で詰まってトラフィックが増えないため結局スコアが伸びなかったのは極めて自然に思える。実際、トップページの商品表示で使われているLowPriced系APIをキャッシュした結果スコアがかなり伸びたりもしたので、アプリケーションの仕様からユーザーストーリー的な部分を把握して改善優先度を決定する、というのがISUCONで最も必要な考え方なんだろうなと感じた。

前回だか前々回だかのisucariでは「購入されやすい椅子」や「購入が多いユーザー」などのように、ベンチによるユーザーごとに特性を再現するギミックが仕込まれていたので今回も購買傾向を分析したりしたいと考えていたが、購入者の情報がUA程度でしか識別できないなどの理由がありやらできなかった。が、もしかしたらそこにもヒントがあったかもしれない。

isuconのアプリケーションチューニングにおいて優先度を決定するには、やはりまずアプリケーションの仕様や傾向を把握することから始めないといけない。gistの資料を読んだり、ログをとったり実装を読んだり。これは仕事でソフトウェア開発をするうえでも同じだし、こういう部分を無視してスコアが稼げないように問題設計がされているのはすごくおもしろい。

「チェアdeスクっと」は名前はダサいが気軽にスタンディングデスクを導入できる最強の製品

いわゆるコロナ禍で自分も在宅ワークを余儀なくされているが、やはりなんといっても座りっぱなしで問題になるのは腰。腰がイカれてくる。

Fitbitで歩数を見ても腰が壊れるのは自明で、自分はかなり通勤経路が長めの人間だったということもありこれまでは余裕で10k歩ほどあるけていたものが、ここ最近では歩いてもせいぜい5k程度にしかならない。歩かないとどうなるかというと、それは下半身のとくにハムストリングスが十分に伸びなくなるため腰痛に悩まされる。下半身を動かさない人間はだれでもみな腰痛に苦しむことになる。

これは座っていることがほとんどの原因なので、これを解決するために自分も据え置き型のスタンディングデスクの導入を検討していた。しかし、いかんせん値段が高い上に置くと机のほとんどのスペースをとられてしまう。昇降デスクも部屋狭いので置く場所がない。

というわけで見つけたのが「チェアdeスクっと」という製品。名前がめちゃくちゃダサい。

この製品はハイバックチェアの背もたれの部分に取り付けることで椅子をスタンディングデスクにできるというもの。

これなら机の上に据え置きにする必要もないし、昇降デスクを買う必要もない。

f:id:IzumiSy:20200905173502j:plain
天板の雰囲気

天板の大きさ的にはMacbook Proの15inchを置いてまあまあいっぱいという程度。

背もたれには以下のようにして固定されている。

f:id:IzumiSy:20200905173434j:plain
背もたれ部分に引っ掛けて固定されている

天板は角度を変えられるようになっている。

自分は若干傾斜があるのが好きなので、以下のような設置角にしている。

f:id:IzumiSy:20200905173446j:plain
横から見た雰囲気

固定の仕組みがかなりよくできているので、相当重いものを置かない限り落ちることはない。とはいえ、当たり前だがアームを付けたりディスプレイを置いたりするのは止めたほうがいい。

一つ気になるのは、椅子の背もたれが動くものだとタイピングをしている最中にすこしグラグラすること。しかし、このあたりは使う分には慣れる。

所感

この製品は極めて日本的だと思う。誰かの記事でも読んだが、そもそも日本は部屋が狭い。そういう部屋に住んでいる人たちのための製品だ。

現状、スタンディングデスクを導入するには机の上に据え置くタイプか別に昇降デスクを購入するしかほとんど選択肢がない。しかし、チェアdeスクっとであれば不要なときはどこかにしまっておけばいい。必要なときだけ場所を取らずにスタンディングデスクにできる。

いい製品だと思う。

なお、余談だが正座をやるようにしたらそこそこ腰痛が改善した。

スタンディングデスク+正座を組み合わせれば腰痛フリーになれるだろうか...

「朝30秒の正座」で腰痛が治る

「朝30秒の正座」で腰痛が治る

Elmアプリケーションにおける型と抽象化手法

Elmは機能を絞った言語であるためScalaHaskellのような高度な抽象化は言語機能上できないが、使う使わないに関わらず知識として「やれること」「やれないこと」を知っておくと、コード表現に幅が出る。

Extensible Record

ざっくり言うとレコードのプロパティを抽象化することができる。

例えば以下のNamableレコードは、nameというプロパティを持つレコードすべてを対象にする。

{-| 特定のレコードに依存しない抽象的なnameというプロパティを持つレコードを対象とする
-}
type alias Namable a
    = { a | name : String }


getName : Namable a -> String
getName { name } =
    name

つまり、以下のようなデータ構造があるとしても、データ構造としては受け付けるものの直接的な依存はしなくなる。

type alias User =
    { name : String
    , email : String
    , age : Int
    }


-- getName関数はUserレコードに依存しないがUserレコードを受け付ける
getName : Namable a -> String
getName { name } =
    name

上記のようなインターフェースになることで、getName関数はUserレコードの構造を持つ値を受け取るとしてもUserレコードのデータ全てに関心があるわけではなく、ただ単にnameという属性のみに関心があるということがインターフェースレベルで表明できる。また、関数の実装も特定のレコードに依存しないものになるため抽象化できる。

一方で「ageやemailの値によってgetName関数の挙動を変える」などの仕様が別とある場合には、それは間違いなく仕様レベルで"getName関数はUserレコードに依存しているべきだ"ということが分かる。なので、そのようなケースではあえてExtensible Recordではなく直接的にレコード名を指定することで関数のインターフェースに依存を表明させるべきだろう。

Narrowing Types

関数が受け取るインターフェースを特定の型に依存させるというのがNarrowing Typesの考え方にあたる。

たとえば以下のようにUserというカスタム型の各バリアントの情報をHTMLにする関数があるとする。

type User
    = UserLoggedIn LoggedInInfo
    | UserSuspended SuspendedInfo
    | UserBanned BannedInfo

viewLoggedIn : User -> Html msg

viewSuspended : User -> Html msg

viewBanned : User -> Html msg

受け取るデータがUser型に限定されている点ではまずまずだが、それでもまだ上記の関数はインタフェースの設計が適切とは言えない。なぜなら、User型はカスタムタイプであるため、コード上で実際に渡る値がバリアントのうちどれであるかはインタフェースからは判断できないからである。こうなると関数をさらに読んでいかなくては実際の挙動が把握できない。

なので、正しくは上記の関数は以下のように、User型の各バリアントが持つデータに依存させるべきだ。こうすることで、さらに関数の依存を限定でき、インタフェースから関数の挙動が推測しやすくなる。

viewLoggedIn : LoggedInInfo -> Html msg 

viewSuspended : SuspendedInfo -> Html msg

viewBanned : BannedInfo -> Html msg

ではこの考え方を抽象化でどのように使うかというと、異なるデータ構造において共通となる型を用意し、抽象化したい関数はその共通の型だけに依存させる。考え方としては若干Extensible Recordに近い。

例えば、以下はMember型とAdmin型に共通なName型を用意し、関数のインタフェースをName型に依存させる例。

-- Member.elm

type Member =
    Member Name


-- Admin.elm

type Admin =
    Admin Name


-- Name.elm

type Name
    = Name String

こうすることで、データとしてName型を持っているものともっていないものを区別できる。また、NameモジュールにはMemberとAdminが必要とする「名前に関するロジック」を凝集させることができるため、Nameという軸でMemberとAdminを抽象化できる。

ここで重要なのがName型を本当に必要な型だけに与えることだ。もしAdminとMemberで名前に関する仕様が異なるのであれば、それは同じName型に依存させてはだめで、AdminとMemberでそれぞれ異なるName型を用意するべきだ。同じ型に依存しているということは、仕様が同じであるということを意味する。

これはプリミティブ型の扱いにも同じことが言える。通常、Stringというのはアプリケーションの中でもっとも頻繁に表れる型だが、Stringへの依存は文字列というほぼ制限のない仕様に対する依存を表明している。しかし、我々が作るアプリケーションにはメールアドレス、ユーザー名、ニックネーム、などの"仕様を持つ文字列"が存在しており、関数やデータ構造はその仕様に特化した型に依存することでインターフェースとして仕様を表現することが望ましい。型と仕様が見つかれば、それはモジュールとして抽象化して抽出できる。

また「ある型が特定の型をもつかどうか」というのは幽霊型というテクニックにもつながる。幽霊型を使うころで状態遷移のパターンを型で制限できたりもする。 izumisy.work

Tagger

Elmはカスタム型もレコードもすべて関数として扱うことができるため、それを利用して任意の値を持つカスタム型のバリアントを受け付けることができる。ライブラリなどを作っていると使う場面がでてくるが、普通のアプリケーション開発ではあまり使う場面があるとは言えない。

type Msg
    = UpdateEmail Email
    | UpdateName Name
    | NoOp


{-| この関数はUpdateEmailのバリアントだけを引数で受け付けることができる
-}
emailUpdating : (Email -> a) -> Cmd msg

つまりタグを持つバリアントというのは、タグを受け付ける関数とイコールである。このような関数をElmにおいてはTagger(タグする関数)と呼ぶ。

あるのか分からないが、たとえば使いどころとして特定のMsgバリアントだけを受け取ってupdateを実行するような関数を実装したいときなどが挙げられる。その場合にはTaggerを使えば、上のemailUpdatingの例のようにUpdateEmailだけを受ける関数が作れる。

抽象化の観点では言えば、上のemailUpdating関数はUpdateEmailに限らずEmail型をタグとして持つものであればなんでも受け入れることができる。したがって、タグの型は限定するが、タグの型が同じでさえあれば値はなんでもよい。

移譲、DIP

DIPに関する記事はここに書いていた。 izumisy.work

また、英語になるがDEVにもモジュールの実装を移譲モジュールで抽象化する件の記事も書いていた。 izumisy.work

所感

書いてて思ったけどこれ全部Elmというよりは静的型付言語に共通する手法という感じがする。

でもElm書いてると細かい言語文法とかライブラリの使い方みたいな場当たり的なものじゃなくて、型を中心にした設計方針みたいなのを考えるほうに気が向くからいいですね。

メルカリでiMac 21inchを売るときのあれこれ(発送とか初期化とか)

先日2019年モデルのiMac 21inchをメルカリで売った。

下取りとか買取で調べると6-7万くらいで買い叩かれる&一度発送しての査定なのでかなり不安(送ったら1000円とかにされたりするかもしれないし)だが、メルカリであれば先に値段が決まるので嬉しい。

手数料は高いが仕方ない。

初期化について

オークション等で譲渡する場合にはiMac本体の初期化は必須。

手順に関しては公式が用意しているものがあるので、これを参照するのがよい。

support.apple.com

ひとつ注意点があり、以下のようなiMacのスペックのダイアログを画像として商品説明に載せる場合には、かならず初期化の前に写真として撮っておく必要あり。

f:id:IzumiSy:20200821102752j:plain
iMacのスペックのダイアログ

一度初期化してしまうと、再セットアップせずにはスペックを見ることができないので、またセットアップからの初期化が必要になってしまう。

シリアルナンバーに関してはそれ用いて保証期間をAppleの公式サイトでチェックしたりする用途で使うようだが、公開してしまうと偽造などに利用されてしまうとかなんとかで念のため隠している。

本当に隠す意味があるのかは不明。

保証について

コメント欄で「この商品は保証書はありますか?」とか聞かれることがあるが、それに関しては「ないが、シリアルナンバーから保証期間を確認できる。この製本の保証期間は〇〇までです」と伝えておけばよい。

www.apple.com

Appleの公式ストアで買うと確実についてこないが、家電量販店などで購入した場合にはその量販店用の保証書がついてくることはあると思う。

発送について

Apple製品というのは箱にも価値があるとか言われるので、人によっては発送するに当たってiMacの箱を包むダンボールをさらに用意したりする。あるいは、iMacを買うと純正の化粧箱を覆うダンボールがさらについてくるが、自分はそれは処分してしまっていた。

だが、自分の場合は追加でダンボール買うのもだるい(あと値段も上げて交渉合戦になりたくない)ので、説明欄に「この商品は純正の箱そのままで送ります」としっかり書いて出品することにした。

この記事を書いた時点でiMac 21inch 2019年モデルはヤマトの140サイズ扱いになる。自分はらくらくメルカリ便で送った。

www.mercari.com

Ubuntu 20.04でUSBのWiFiアダプタ(WDC-300SU2SBK)を認識させる方法

インターネットで調べたところ、どうやらUbuntuがサポートするrtl8192cuというチップとして認識させれば動くとのこと。

というわけで、rtl8192cuのモジュールをmodprobeでロードし、lsusbで分かったベンダIDとプロダクトIDをカーネルに認識させる。

$ sudo modprobe rtl8192cu
$ echo "056E 4009" | sudo tee /sys/bus/usb/drivers/rtl8192cu/new_id

こんな感じで、対象となるモジュール名の配下に置かれている new_id ファイルへデバイスの情報を書き込むとドライバの対象として未登録の機器であっても認識させることができる。つまり、実質的にどんな野良WiFiアダプタであっても中のチップセットの種類さえサポートされているものであれば、この方法で動かすことができる。

あとはudevを使ったり/etc/rc.localに上のコマンドを書いておくなりして、起動時にWiFiアダプタ用のモジュールをロードし自動的にネットワークへ繋がるようにすればよい。

askubuntu.com