🐟🐟支笏湖でお風呂に入ってチップを食べた🐟🐟

ことりんと夏休みの小旅行。

支笏湖。新千歳空港からのアクセスは、札幌に行くのと変わらないかもしれない。

ひつじのことりんを引き連れて2泊3日の旅行に行ってきた。

地味に人生初の一人旅。

https://x.com/025cm/status/1955156415850611153

到着早々1人と1匹で湖畔でおやつタイム。

達人プログラマーを4章分くらい、一緒に読んだね。

https://x.com/025cm/status/1955162027095371784

宿からの迎えのバスに乗る。

丸駒温泉に泊まった。

迎えにきた人が話好きな人で、9月22・23日に大通公園のオータムフェスタに店出すんだ、食べにきてよって誘われた。気になる。

京都から札幌に来たのだと話していたら、美味しい料亭を教えてもらえた。

なんでも柊家で18年間修業した人のお店とか。

早速京都の友達に、次遊びに行く時はこれを食べるぞってLINEをした。 www.kyotokiyojirou.com

車窓から見える湖が綺麗だった。

https://x.com/025cm/status/1955193372270006337

旅館についてからは、持参したお弁当を食べて、本を読んだりコードを書いたり内省をしたり、、、、

湖の周りをたくさん散歩した。

寝付けなくて、蜂蜜と遠雷をずっと読んでた。

翌朝はバイキングへ。

全部美味しかった。美味しくないものが何にもなかった。

お昼ご飯に備えて控えめにしようって思ってたはずなのに、白米もパンもどっちも食べちゃったし、3回くらい配膳台と席を往復しちゃった。

超豪華な朝ごはん

チップをながめることりん(まんまるの頭)

東京拠点はにぎやか①

5月11日 ~ 23日は、東京拠点に出張をしていたのだけど、 普段対面で会えない同僚とお話ができたりして、たのしかったので、 忘れないうちに色々、考えたり感じたことを文字にする。 まずは2人。 (本当は文字に起こして記録したい人がまだ、パッと思いつくだけでも他に5人いる。)


「ぼーっとする一日?3ヶ月に一回くらい置きかなぁ。」

ちょっと、この人の底が読めないな、正体を掴むとっかかりがないなと思っている上司がいる。

たくさん物事を考えていること、周りの人に安心感を与えていること、場を動かす力を持っていること。

ぜんぶ、「こうなれたらいいな」って思っている姿で、

「どうしたらこの人っぽさを獲得できるのだろう」という意味で、興味を感じていた。

今回、ひょんなことから、ちょっとだけその方の仕事の有り様に迫れた感じがあった。

えび「資料とか眺めていると、たまに〇〇さんのお名前見かけるんですよね」

えび「元々エンジニアされていたんですか?」

ここから少しだけ、お仕事との向き合い方を伺うことができて。

まず思ったこと。その人は、対象と向き合っているときの思考量が多かった。

行き道や帰りの電車でも、「任意の課題」について考えているみたいだった。

「俺、常に何か、考えがいのある対象探しているわ。」

「何かないと落ち着かないんだよね。」

あとは、行動の試行回数が多い感じもした。

「5分、10分考えて答えが出なかったら、寝かせるかも。感覚的に答えが出てるなら動く。」

その人は、メールの内容を全て覚えているらしかった。

直近、私が送った、どうでもいいような極々しょぼいトピック(追わなくてもなんら支障がない話)についても、

ちゃんと読んでいて、ちゃんと現状を把握されていた。

全部全部真似はできないにせよ、あり方自体がなんとなく、印象に残った。

「休みたいな〜って、定期的にぼーっとしたい日が来るんだよね」

「うーん、大体3ヶ月に一回おきくらいかな」

同じ人間のはずなのに共感が難しい。

違ったあり方をしている人の話を聞くと、自分の中に、いつもの自分と違った風が流れる感じがして、それは内省をしすぎる傾向がある私にとっては救いであり、豊かな時間だと思っているような感じがする。


「オレ、この二週間えびちゃんと2分しか話してない気がするわ。」

最終日前夜。

上司、「オレ、この二週間えびちゃんと2分しか話してない気がするわ。」

そう、確かに話せていなかった。

えび「いっぱいお話ししましょう」

内心焦りでいっぱい。

軽やかに無難にコミュニケーションを取ることに苦手意識がある。

どうしよう、とりあえず趣味の話?

上司、そういえば好きな作家は松本清張と言っていたな。やばい、読んだことがない。 うむむ。。。。

いきなり重い話題を振るのもおかしい。まずは軽く、ジャブを打ちたい。 そう、

「おはようございます〜、今日はちょっと暑いですね〜〜」

くらいの、これくらいの温度感のやつ。

とはいえ、もう夕方。

その日の気温の話は朝にするのが適切な感じがする。夕方に「今日は暑かったですね〜〜」はなんか、、、うーん。

なんか違う。

せっかく久しぶりに話す上司。

好きか嫌いかと言われればまあ快く思っている相手。

内心感じている親しみと、外に表出される話題の釣り合いが取れていない感じもする。

そして、どうせなら「あなたに関心がありますよ」ということを表現したい。 うーん。。。。

焦りに焦りに焦り、とりあえずなんとなく話してみるものの、いまいち盛り上がりにかけ、、、、

えび「次来るときは6分話しましょう!!!」

上司「6分だけなんかい!!!!!」

おしまい。

「最終日になっちゃいましたね、もっとお話をしたかったです。」

言いたかったことはこれ、これだったはず。

次会う時までに、お話ししたことをちゃんとメモっておこう。

目の前にいない時は、いっぱい思いついているのに、

目の前にいると、なんでか内心が忙しくなりすぎる。

会話回しがド下手なくせに、なんか、「まずは軽い話から!!徐々に、徐々に本当に話したい方へ誘導を。。。」と、

色をかきすぎる癖もある。

本当に、、、、、、本当に。 がんばります。

しかし上司。話している人に合わせてコミュニケーションとる人で、 私と会話してる時だけ「えへへ。うふふ。」的な笑い方をするのを本当にやめてもらいたい(ありがたいなと思っています)

循環参照を発生させる

上部グラフエリア

  • 青いライン: 全体のHeap使用量の推移(時系列)
  • 緑・オレンジエリア: VM Trackerの各種メモリ使用量

下部統計テーブル

列名 意味 見るべきポイント
Category オブジェクトの種類 どんなオブジェクトが多いか
Persistent 残存メモリ量 メモリリークの疑いがあるサイズ
# Persistent 残存オブジェクト数 解放されていないオブジェクト数
# Transient 一時オブジェクト数 作成→解放されたオブジェクト数
Total Bytes 総メモリ使用量 全体でどれだけ使ったか
# Total 総オブジェクト数 作成された全オブジェクト数

循環参照を起こしたパターン

通常時

例:

import SwiftUI

struct MatrixRainView: View {
    // MARK: - メモリテスト用State
    @State private var testObjects: Person? = nil
    var body: some View {
        // MatrixRainViewは画面全体のsizeの値をMatrixRainCharactersに渡している。
        GeometryReader { proxy in
            let size = proxy.size
            VStack {
                Spacer()
                // MARK: - メモリテスト用ボタン
                HStack {
                    Button("循環参照作成") {
                        createRetainCycle()
                    }
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .background(Color.red.opacity(0.3))
                    .foregroundColor(.white)
                    .cornerRadius(4)

                    Button("オブジェクト解放") {
                        releaseObjects()
                    }
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .background(Color.green.opacity(0.3))
                    .foregroundColor(.white)
                    .cornerRadius(4)

                    Text("Count: \(testObjects)")
                        .foregroundColor(.white)
                        .font(.caption)
                }
                .padding(.top, 50)

                Spacer()
            }
        }
    }

    // MARK: - メモリテスト用メソッド
    private func createRetainCycle() {
        testObjects = Person(name: "えびちゃんだよ")
    }

    private func releaseObjects() {

        print(testObjects?.getName() ?? "testObjectsはnilだよ")
        testObjects = nil // Person内で循環参照が起きているのでdeinitが呼ばれない
    }
}


struct MatrixRainView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

// MARK: Random Characters
// Your Own
let constant = "abcdefghijklmnopqrstuvwxyzabcquepaje123jdj09"


// MARK: - メモリテスト用クラス(循環参照)
class Person {
    let name: String
    var instrument: String = ""

    init(name: String) {
        self.name = name
    }
//    lazy var getName: () -> String = {
//            return "\(self.name) " // selfの参照カウントが+1
//        }
    lazy var getName: () -> String = { [weak self] in
        return "\(self?.name) " // selfの参照カウントが+1
        }

    deinit {
        print("❌ \(name) is being deinitialized")
    }
}

循環参照させたい時はこっち

    lazy var getName: () -> String = {
            return "\(self.name) " // selfの参照カウントが+1
       }

させたくない時はこっち

    lazy var getName: () -> String = { [weak self] in
        return "\(self?.name) " // selfの参照カウントが+1
        }

参考

shiba1014.medium.com

アプレンティスシップ・パターン 徒弟制度に学ぶ熟練技術者の技と心得 (とりあえず1章まで

前書き

優れたプログラマになる方法を教えるのではなく、 優れたプログラマになるための学び方を教えるのです

本書によせて

私はその思考の道具をパターンと呼んでいます。 確立されたパターンの名前を知るだけでも、大いに役立ちます。パターン名を言うことで、その詳細を話さなくても議論できます。

この辺はすごく社会学みを感じちゃう。

まえがき

良き指導者を見つける(Find Mentors)は、それ自身優れた実績のあるパターンです。同席する (RubbingElbows)と組み合わせることでさらに効果を発揮します。 一方で無知をさらけだす(Expose Your Ignorance)は無知に向き合う (Confront Your Ignorance) と得意領域へ撤退 (Retreat into Competence)などの支援パターンに依存しており、上手く使用するにはちょっとした細やかさを必要とします。

この書き方好き。

1 章 序 論

  • 「自分の行いの中の不適切さを認識し、解決方法を求める」意志
  • 実践的であることへの熱望。
  • 自分達の運命のコントロールと責任を持つこと
  • 「正しい」プロセスを使用するよりは、高いスキルを持つことが重要「物事を誰が行っても常に上手くいくとは限らないことを受け入れます」

これは結構、最後の一つはきつい言い方だけどそう。

その時の身の丈にあっていない本を読んでも必要な情報を得ることができない。

  • 学習する最善の方法は、あなたが学びたいスキルを使用して同じゴール を達成しようとしている人々と同じ部屋にいることです。

ソフトウェア職人気質とは、継続的な学習と成長を重視する価値観とコミュニティのことかなーと理解した。

アプレンティスであることはどういうことか

「今まで行ったことや今行っていることをより良く、さらに賢く、もっと速く行う方法が常にあるという態度を基本的に持つことだと思います。 徒弟制度は、より良い方法へと発展し、より良い方法を探し、より良く・さらに賢く・もっと速く行う方法を学ぶことを強制する人々、会社、状況を探す、状態・プロセスです」 問題に対処する建設的な方法へと導いてくれる内面的な動機に多くの価値がある

最近、自己完結的をやりすぎて周りにもうちょっと頼ってくださいに近いことを言われた身としては「内面的な動機」と言う言葉にちょっとした引っ掛かりを覚える節がある。

自己完結的に振る舞えること・内面の動機の強度に頼った行動をとることは、得意だけれども、ちょっと謙虚に向き合いたい時期。

「それは、安易な成功で得られる内面的な量ではありません。高い知性について人々に話すことで、人々に与えられるものではありません。 見かけ上の賢さではなく、挑戦することを楽しみ、間違うことを熟練職人への道のりとして活用することに価値を置くことを教えることで、自分自身のために身に付けるものです」

理想的な状況は、同僚のアプレンティス、ジャーニーマン、それに 1 人の熟練職人から構成される小さなチームの中にあなたがいることです。

現実で得ることが難しい話に注目しすぎても仕方ないかって思ってこの辺は読み飛ばしちゃったな。

「今までのやり方をより良く、賢く、速く行う方法が常にある」という態度を持つことがアプレンティスの核心っぽそう。

ジャーニーマンであることはどういうことか

ジャーニーマンの責任は、アプレンティスの責任よりは広範囲です。 そのため、ジャーニーマンが失敗すると、多くの損害をもたらす可能性があります。私達が説明するパターンによっては、ジャーニーマンに対しては適切ではないものもあります。 なぜなら、ジャーニーマンは、彼を良き指導者とみなしている人々に対する重大な責任をまさに持っているからです。

ジャーニーマンとは 「技術的に成長しながら、チームや他の人とのつながりを重視する中級者」 のことっぽそう。 中間管理職。

コミュニティに出てる人は大なり小なりジャーニーマンっぽくなりがちな気がしてる。

所属会社や所属コミュニティの看板を、かなしかな一定背負ってしまうような。

熟練職人であることはどういうことか

技芸の熟達には、アプレンティスやジャーニーマンのすべての役割を行うことに加えて、ソフトウェア業界を発展させることに焦点を当てることも含まれます。

徒弟制度とは

チームリーダーやプロジェクトマネージャ向けに書いているのであれば、理想的な徒弟制度を構築するための方法を示すことは意味があるでしょう。なぜなら、そのような人達は、その種の経験を促進する権限を実際に持っているからです。

ほとんどの新人の経験は、理想的な徒弟制度とは似ていませんので、徒弟制度の今日の考えは、主に心構えです

自分の置かれた環境から自分なりの徒弟制度を構築するためのステップを踏む準備をすることです。

実際、理想からはほど遠い状況で、ほとんどの人々は、自分の徒弟制度のために格闘する必要があります。 横柄で無能なマネージャ、モチベーションの低い同僚、不可能な締め切りに直面するかもしれませんし、初心者の開発者を使役馬のように扱い、1 台の PC と役に立たないインターネットへの接続がある小さい四角の馬房に開発者を詰め込んでいるような環境で働くことになるかもしれません。 本書のすべての教訓は、次の高い段階に到達するために、このような環境を克服しなければならなかった(私達のような)人々の経験から得られています。

スタンスとして好き。

私はどうやら対象読者に入りそう。

アプレンティスシップ・パターンとは

パターンが共有する他の性質は、世代継承性の性質です。パターンを適用するごとに毎回異なった結果になるべきであり、パターンを適切な状況で使用すれば、あなたの働く環境を改善してくれるはずです。

パターンは、適用するたびに同じ結果となるアルゴリズムではありません。 その代わりに、パターンは問題を解決し、新たなパターンを作り出す道具です。こつは、自分で判断して、自分が望む問題を選択することです。

ここの言葉の意味、よくわかってない。

読むうちにわかるでしょう(慢心)

パターンはどこに由来するのか

本書は、最初は Dave の見習い期間の経験話から抽出され、その後、Ade の話で検証および補強が行われ、最後に、数年から数十年の経験レベルを持つ約 30 名の人々の経験に対して検証されました。

信頼しろよって言われてる心地。

次に向かう先

パターンを選択し、組み合わせたり、あなた固有の状況に数知れないやり方で適応させたりする力を、あな たが持っていることを忘れないでください。

何年か後に、パターンによっては、突然あなたに関係するようになるかもしれませんし、逆に不適切に感じるようになるかもしれません。

見習い期間はあなたのキャリアにおける、ある時期にすぎません。

あなたの学習の機会を最大限にするために、収入をすぐに最大限にするという願望を先に延ばす時期です。そのため、ある程度の身勝手さが許される期間です。 そして、一旦、その期間が終われば、皆さんの優先順位を入れ替える必要があるでしょう。

年次的にはそろそろ、アプレンティスの自認から卒業した方がいいんだよな。

(2025/08/10)

2 章 カップを空にする

本章のパターンは、あなたが見習い期間を、正しく、開かれた心で開始するた めの道具を提供します。

最初の言語(Your First Language)

独学で言語を学ぶのは可能ですが、専門家と交流しなければ、言語の精神を学ぶのに長い時間を要します。

個々の言語は、異なったパラダイムを使って問題を解く機会を提供します。 最初の言語を乗り越える際には、すでに熟知している言語とは全く異なったアプロ ーチを取っている言語を学ぶ機会を求めてください。

白帯(The White Belt)

状況

あなたは、最初の言語を深く理解し、快適に歩いていますが、能力は停滞しています。

同僚は、あなたの能力を認めてくれていて、あなたが専門とする領域の問題を解決するのに助けを求めてきます。 問題

あなたは新たなことを学ぼうと努力しているのですが、新たなスキルを修得する のがなぜか以前より困難になっているように思えます。最善の努力をしているにも かかわらず、自己学習のペースは遅くなっているように思えます。自己成長が停滞 しているのではないかと恐れています。

新たな知識が入ってこられるように、私達は過去の経験と先入観を脇に退けることができなければなりません。

2 番目のプログラミング言語を学ぼうとする時には、それはとりわけ難しいです。なぜなら、スキルを向上させるために、生産性を犠牲にしなければならない、おそらく最初の機会だからです。

新しい知識を十分に理解する時が来るまでは、新しい知識と古い知識を融合させるのを避けなければなりません。

新たな方法を一旦修得して飛躍的に前進するために、ある程度の生産性が短期的には犠牲になるかもしれません。

たとえば、1 つのプログラミングパラダイム(たとえば、命令的、オブジェクト指向的、関数的、配列 / ベクター指向的など)で書いたことがあるプログラムを取り上げて、異なったパラダイムを使用する言語でそれを実装してみてください。 知っている言語がすべて同じパラダイム(たとえば、オブジェクト指向)を使用しているのであれば、新たなパラダイムを学ぶ機会になります。

情熱を放つ(Unleash Your Enthusiasm)

チームの力学は常に考慮すべきです。あなたの興奮を受け入れないチームに属しているならば、自分の情熱を高める方法を見つける必要があります。

経験のある開発者が欲しいと思っている、自由な想像力と情熱といったものをあなたは提 供するでしょう。

それは、あなたのキャリアの中で、リスクを取って、自分の考えを述べることが理にかなっている時期です。失うものはほとんどありません。あなたの考えと情熱が、知性と多様性をチームに加えます。 究極的には、あなたの情熱を放つことは、アプレンティスとしての比較的少ない責任の 1 つです。あなたは、深い知識や高い生産性をもたらさないかもしれません。 しかし、チームに何らかの情熱を注ぎ込み、あらゆることを質問するのはあなたの義務です。あなたは、新鮮な見方を持つ独特な(そして、一時的な)立場にいます。

その新鮮な見方のおかげで、改善のための有益な提案ができます。

職人も弟子から学ぶわけです。意気込みのある初心者は職人を心機一転させるだけではなく、外部から新たな考えを持ち込むことで職人に挑戦するのです。

弟子の選定をうまく行えば、熟練職人をさらに生産的にすることさえできるのです。

具体的スキル(Concrete Skills)

状況

現在よりも良い学習環境を提供してくれる、職人の才能にあふれたチームに入り、役割を担いたいと思っています。

問題

あいにく、チームの仕事に直接貢献できない人を採用するリスクを冒す気が、そのチームにはありません。そのチームでは、何か簡単な手作業の業務を自動化するような間接的な貢献さえできない可能性があります。

解決方法

具体的スキルを獲得し、それを維持してください。

だいぶ力強い話をしておる。

あなたが持っている具体的スキルは、「今日あなたを採用したら、月曜日の朝から何ができて、どのように貢献してくれますか」という質問に対する答えです。

最初の言語(Your First Language)の深い理解があなたへの信用を確立するのに役立ち、チームに対して非常に有益であることを証明してくれるはずです。

ここ率直で好き

ジャーニーマンの役割へ移り始めると、それらのスキルへの依存は少なくなります。なぜなら、あなたの評判、以前の仕事のポートフォリオ、あなたがチームにもたらす深い品質に基づいて、採用され始めるからです。それまでは、あなたの長所は少しだけ目立っていなければなりません。

無知をさらけ出す(Expose Your Ignorance)

社会心理学者 Carol Dweck による調査によれば、有能に見えるという必要性は、ほとんどの工業化社会の人々に深くしみ込んでいます。私達の毎日の生活にソフトウェアが深く入り込んでおり、そのような社会は、開発者としてのあなたの能力にますます依存してきています。

彼らに本当のことを話してください。彼らが望んでいることを理解し始めたばかりであり、望まれたことを提供する方法を学んでいる最中であることを、彼らに知ってもらってください。

あなたが知らないことを知っている振りをするのではなく、あなたの学習能力で安心さ せてください。

そうすることで、あなたの評判は、あなたがすでに知っていることではなく、あなたの学習能力に対して築かれます。

職人が持てる最も重要な特徴の 1 つは、無知な領域を特定して、そのような領域を減らすことに努めながら学習する能力です。

見習い期間が終わるまでには、2、3 の技術について強い知識の糸を持つことにな ります。

それらの糸で、少ない数のプラットフォームや領域上に頑強なソフトウェア・アプリケーションを紡ぐことができます。 熟練職人は、無数の糸からタペストリーを紡ぐ能力を持っています。 熟練職人は、好きな糸や組み合わせを持ち、糸の数は膨大で、広い範囲の技術環境に対応できます。長い道のり(The Long Road)があなたを導く先は、そのような熟練職人になることです。能力があるように見せかけるよりも、あなたの無知をさらけだし、無知を正面から見据えることで、持っていない糸を素早く紡げるようになります。

仕事について、実際に理解していない 5 つの事柄を書き出してください。 そのリストを、他人が見える場所に張ってください。仕事が変わるたびにそのリストを更 新する習慣を身に付けてください。

無知に向き合う(Confront Your Ignorance)

技芸への取り組みの顕著な面の 1 つは、あなた個人の成長のためにチームや顧客を利用するのではなく、自分自身の興味よりも、周りの人々のより広い興味を優先する意思です。

自分自身の無知に向き合うだけでは、何も成し遂げないで情報を求めるだけの傲慢な人になります。一方、問題を解決するのに、無知であることを分からずに無知をさらけ出すと、過度な謙虚と頼りなさになります。

難しいこと(The Deep End)

筆者らは、遂行できる最も挑戦的な仕事を求めなさいと主張していますが、水のレベルがあなたの頭より高ければ、あなたは溺れているということを忘れてはいけません。

必要とした時に助けてくれる良き指導者を見つける(Find Mentors)や気の合った者同士(Kindred Spirits)によって、このパターンのリスクを補うのは、あなたの責任です。

長い道のり(The Long Road)の途中では、これは普通であり避けることができないこと です。

無知をさらけ出す(Expose Your Ignorance)と無知に向き合う(ConfrontYour Ignorance)ことが、自分の無能さの恐怖を克服するための架け橋です。

得意領域へ撤退(Retreat into Competence)

カタパルトから投げられる石のように、一度撤退してから前に進んでください。 平静を取り戻すためにあなたの得意領域へ撤退してください。

どれだけの期間、どこまで撤退するかについて意識的な制限がないと、恐れや失敗に対して単に屈していることになります。

あなたが本当によく知っている自己完結しているものを取り上げて、それを再実装してください。

【SwiftUI】スマホの画面に雪を降らせてみた

暑くなってきましたね。 雪が舞い散るアニメーションをSwiftUIで作ってみました。

考え方

  • 雪の一粒一粒を表現するオブジェクトを作成
  • それをランダムな座標に散りばめつつ、タイマーで座標を逐次更新する
  • 各雪オブジェクトはランダムな速度とサイズを持ち、画面の下に到達する都度再配置される
  • かくして、雪は無限に降り続ける

コード全体の流れ

  1. パーティクルオブジェクトを作成し、ランダムな位置・速度・サイズを持たせる
  2. タイマーのイベントに応じて、パーティクルの座標を下に更新する

実装全体

コピペで動きます。

import SwiftUI

// 雪を降らせる
struct SnowfallView: View {
    /// パーティクルの配列を持たせる
    @State private var snowParticles: [SnowParticle] = []
    /// タイマー: 0.05秒ごとにイベントを発生させることで、アニメーションを更新
    private let timer = Timer.publish(every: 0.05, on: .main, in: .common).autoconnect()

    var body: some View {
        GeometryReader { geometry in
            ZStack {
                // パーティクルを描画
                ForEach(snowParticles) { particle in
                    Circle()
                        .fill(Color.white.opacity(0.6)) // 雪一粒一粒の透明度は60%
                        .frame(width: particle.size, height: particle.size) // パーティクルのサイズ
                        .position(x: particle.x, y: particle.y) // パーティクルの位置
                }
            }
            .onAppear{
                // ビューの表示時にパーティクルを初期化する
                initSnowParticles(in: geometry.size)
            }
            .onReceive(timer) { _ in
                // タイマーイベントでパーティクルの位置を更新
                updateSnowParticles(in: geometry.size)
            }
        }
        .background(
            Image("backgroundImage")
                .resizable()
                .scaledToFill()
        )
        .ignoresSafeArea()
    }

    /// 初期の雪の粒子を生成
    /// - Parameter size: 画面サイズ
    private func initSnowParticles(in size: CGSize) {
        /// 雪の粒子数
        let snowCount = 100
        /// 落下速度の取りうる範囲
        let speedRange: ClosedRange<CGFloat> = 0.6...3.0
        /// 取りうる粒子のサイズ
        let sizeRange: ClosedRange<CGFloat> = 5...18
        // 雪の粒子を指定数生成し、ランダムな初期位置、速度、サイズを設定
        snowParticles = (0..<snowCount).map { _ in
            SnowParticle(
                x: CGFloat.random(in: 0...size.width), // X座標をランダムに設定
                y: CGFloat.random(in: 0...size.height), // Y座標を画面全体にランダムに設定
                speed: CGFloat.random(in: speedRange), // 落下速度をランダムに設定6
                size: CGFloat.random(in: sizeRange) // 粒子のサイズをランダムに設定
            )
        }
    }

    /// 雪の粒子の位置を更新
    /// - Parameter size: 画面サイズ
    private func updateSnowParticles(in size: CGSize) {
        // 各パーティクルの位置を更新し、下に落下させる
        for index in snowParticles.indices {
            snowParticles[index].y += snowParticles[index].speed // Y座標を速度分だけ増加
            // パーティクルが画面下に出た場合、上部に再生成
            if snowParticles[index].y > size.height {
                snowParticles[index].y = -10 // 画面の上に移動
                snowParticles[index].x = CGFloat.random(in: 0...size.width) // X座標をランダムに設定
            }
        }
    }
}

// 雪一粒一粒を表現するオブジェクト
struct SnowParticle: Identifiable {
    let id = UUID()
    // 座標
    var x: CGFloat
    var y: CGFloat
    // 速度
    var speed: CGFloat
    // サイズ
    var size: CGFloat
}

プロトコルスタックとサーバはどうやって通信を確立するのか(ネットワークはなぜつながるのか 読書記録②)

この記事の続き。

xvi-pea.hatenablog.com

プロトコルスタック

階層関係性的には、 アプリケーション > Socketライブラリ > プロトコルスタック 的な感じ。

  • アプリケーション層

ユーザーが操作するアプリケーション(例: ブラウザ、FTPクライアント)。 Socketライブラリを通じて通信操作を行う。

アプリケーションとプロトコルスタックTCP/IP)を仲介する。 ソケットを作成し、データ送受信に必要な情報をプロトコルスタックに伝える。

データ送受信の実際の制御を行う。 TCP: 信頼性の高いデータ転送を提供(例: ファイルダウンロード、HTTP通信)。 UDP: 軽量かつ低遅延なデータ転送を提供(例: DNSクエリ、ストリーミング)。

サーバーとconnectを行う手順

connect呼び出し時に、TCPは「3ウェイハンドシェイク」を開始する。

  • SYN(Synchronize): クライアントがサーバに接続要求を送信。
  • SYN-ACK: サーバがクライアントに応答し、自身の接続情報を送信。
  • ACK: クライアントがサーバに接続確認を送信。

ハンドシェイクが成功すると、接続が確立されます。

  1. ソケットを作成する アプリケーション側から命令が伝えられたらソケットを作成する。 (※ ソケットは、通信に必要な情報(IPアドレス、ポート番号など)を格納するためのデータ構造のこと。) このとき、ソケット一つ分のメモリ領域を確保して、初期状態として「未接続状態」であることを記録する。

  2. ソケットの作成が完了したことをアプリケーション側に伝える ソケットを示すディスクリプタをアプリケーション側に伝える(プロトコルスタック上にはたくさんのスタックがあるのが通常なので、ディスクリプタを使って通信を識別するのは大変理にかなっている感じする)

  3. アプリケーションはconnectを呼び出す これを受けてプロトコルスタックは自分側のソケットに必要な情報を付加し、サーバ側に「通信可能な状態になったよ」と通知を行う。 => サーバ側も自分が通信する相手がどこの誰なのか認識する。

  4. サーバ側からconnectが返ってくる この状態では、まだデータの送受信は始まらない。 ソケットの状態は「接続待機中」または「SYN-RECEIVED」として記録される。 このタイミングで、プロトコルスタックTCP担当は接続相手のIPアドレスとポート番号を認識する。

  5. 「接続する」ステータスをサーバ側に渡し、サーバ側のTCP担当はソケットのステータスを「接続中」に変更する

  6. ソケットのステータスを「接続済み」に変更

クライアントのソケットが「接続済み」に移行する。 プロトコルスタックは制御をアプリケーションに戻し、これによりデータ送受信が可能になる。

プロトコルスタックは一定送信予定のデータを貯める動きをする

メモリ・通信効率的な観点から、プロトコルスタックは送信前に一定データを貯める動きをする。 これはデータ量か経過時間が規定値に達するまで実行されつづける。

ただしデータ送信時のオプション設定をいじればこの限りではない。

プロトコルスタックとサーバーがデータを送受信する際の工夫

  • シーケンス番号

データがパケットの漏れなくサーバ側に届いていることを確認する際に使用する。

  • ウィンドウ制御

データの送信量を受信側の処理能力に合わせるための仕組み。 (受信能力を超えるパケットが届いてしまうとバッファが溢れ、データ損失が発生する可能性が生じる。)

  • うまくデータが届いていなかった場合は再送する

  • 規定回数通信に失敗したらアプリケーション側にエラーを通知する

メモ

通信後のデータのやり取り・切断時の動きも、基本的に通信確立時と考え方は同じ。

RDRAを使って警察の証拠品管理業務の要件整理をおこなう~フェーズ1

※ 自分の理解の整理のために書いています(とても読みにくいと思う)

RDRAとは

  • 用件定義を4つのフェーズに分けて段階的に進める手法

ドメイン理解用の参考文献

各フェーズの内容

フェーズ1:BUCの洗い出し ~ スコープと骨格の決定 ~

目的:初期要望から要件のスコープと骨格を決める やること:初期要望からシステム化対象を「アクター・外部システム・ビジネスポリシー」の3つの視点で表す - 「アクター・外部システム」は要件のスコープ - 「ビジネスポリシー」は骨格の決定に関与する - システム化は人のために行うので、アクターを明らかにすることが出発点になる 外部のシステムの要望を満たす場合は外部システムを明らかにすることが出発点になる フェーズ1は正確さよりも可能性のあるものを洗い出すことに集中する

成果物として整理する概念とフェーズ1における位置付け

  • アクター:可能性の範囲を明らかにするために、正確性より可能性に着目し整理を行う。
- 管理責任者    証拠物件管理の総括責任、方針決定を行う警察署長・課長クラス
- 保管責任者   保管設備・物件の直接管理、点検実施を行う警部・警部補クラス
  • 外部システム:外部システムに価値を与える場合は外部システムの洗い出しが必要になる。この時、手段としての外部システムは含めない。
- 検察庁システム  送致・保管転換情報の連携を行う
- 科捜研システム 鑑定嘱託・結果受領の情報連携を行う
  • ビジネスポリシー:ビジネスにおいて大事にしている関心事を表す
- 証拠価値保全の原則    証拠物件は犯罪立証の重要資料であり、滅失・毀損・変質・混合・散逸を絶対に防ぐ
- 個人保管禁止の原則   個人による保管を禁止し、必ず定められた保管設備で管理する
  • ビジネスパラメータ:バリエーション的なもの。多様な状況に対応するために大事にしている関心ごとを表現する
- 証拠物件分類 一般物件、特殊物件(現金・有価証券・貴金属、銃砲刀剣類・火薬類、覚醒剤・大麻等薬物)、DNA型鑑定資料、電磁的記録媒体、大型・特殊形状物件の分類
- 保管期間・処分区分   短期保管(1ヶ月以内処分予定)、長期保管(1ヶ月超の継続保管)、送致済、処分済の区分
  • 情報:ビジネスを推進するために必要な概念
- 証拠物件   押収された物件の基本情報と分類情報を管理するため
- 押収調書  証拠物件の押収時の詳細情報を記録するため
  • 状態:管理しているものを明らかにする
- 保管状態   証拠物件の保管場所と保管状況の変化を管理する
- 仮出状態  証拠物件の仮出申請から返納完了までの状態変化を管理する
  • 業務:システム化対象の業務を明らかにする
- 証拠物件受入管理   証拠物件押収受入    押収された証拠物件の受入手続きを行う
- 証拠物件受入管理  証拠物件分類判定    物件の種類に応じた分類・保管設備判定を行う

図示

洗い出した「業務」と「ビジネスポリシー」からを参考に「業務」を行うアクターと関係する外部システムを検討し、必要な「BUC」を洗出す

「BUC」を遂行するために必要な「情報」を洗い出し、「情報」ファイルのフォーマットで出力する

「BUC」を管理するために必要な「状態モデル」を洗い出す、「状態」ファイルのフォーマットで出力する