おもちゃバコ

中身スカスカ♡

「知識ゼロから学ぶソフトウェアプロジェクト管理」を読んだ

こんにちは

「知識ゼロから学ぶソフトウェアプロジェクト管理」を読んだ感想です。


書籍

対象

  • エンジニア視点のソフトウェア開発におけるプロジェクト管理について学びたい人
  • ソフトウェア開発の体制を改善したいけど何をすれば良いか分からない人

本書は「エンジニア」寄りの視点からソフトウェア開発におけるプロジェクト管理について,筆者の経験談と各種参考文献を交えて解説しています。
ノウハウ集的な内容であり,プロジェクト管理という正解を出しにくい内容についての本ですが,砕けた文体なのもあって比較的楽しく読み進めることが出来ました。

自組織の体制について見直したい人向けの本だと感じます。


メモ

最早,メモというより個人の感想です。

個人的に本書が伝えたい内容は以下の3点だと思った。

  • 「時間が無い」を言い訳に問題から目を背けるな
  • ソフトウェア開発では、残業と人員増加はよく考えてから行え
  • ソフトウェア開発手法の正解は分からないが、失敗しないようにある程度の制御は出来る

第1章 まえがき

PMBOK: 専門家がプロジェクト成功への方法論やスキルなどをまとめたもの
CMMI: システム開発組織のプロセス成熟度をモデル化したもの

PMBOKとかCMMIなどが話題になるけど、登場当初と今を比較すると内容が膨大になっており、理解した頃には古い情報になっているかもしれない。
 IT技術だけでなく他分野にも同じ事が言えると思う。
 知識や事柄を表面的に理解するだけでなく、それが誕生するまでの背景や思想を学ぶことで自分の経験に活かしていきたいね。

時間が無い・忙しいを言い訳にして、改善する事を怠り、同じ過ちを繰返す。
 自分も能力不足やミスした時の言い訳、面倒事を避けるために「時間が無い」と言うことがあるので、マジで便利な言葉だと思う。
 時間が無いのは皆同じなので、言わないように反省する。

第2章 典型的な失敗例

デンバー空港、みずほ銀行、アリアン5ロケットのソフトウェア問題について
 当事者になりたくない内容なので、賢者になるために歴史を学びたいと思う。
 内容と直接関係ないけど、結果論で放言高論しすぎないようにしたいと感じた。

モチベーションの欠如は事故を引き起こしやすい
 その通りだと思うけど、人間なので難しい問題だとも感じる。
 仕事に対する意識の差は、サビ残やハラスメントを引き起こしやすいしね。

第3章 人が全て

日本と海外のIT企業を比較して、日本企業の生産効率が悪い理由が述べられている。
 プロジェクトがうまくいかなかった例を提示し、その原因と解決策について述べている点は良かったが、エンジニア視点の話の展開の仕方に違和感が感じた。

日本と海外のIT企業を比較して、日本のソフトウェア開発体制が如何に悪いかが述べられている。
 ただ、マイクロソフトを比較対象として、日本のIT企業の開発体制は遅れているって言うのはどうなの...?って感じた。
 労働環境だけで言えば、海外のゲーム開発には「クランチ」と呼ばれる文化があり、これは日本企業以上に過酷だと思う(反例を上げることに意味はないけどね)。
 まぁ、日本企業が遅れているのは正しい気がする。
 お持ち帰り検討が多すぎて判断が遅いし、効率化を図ろうとすると「仕事が無くなる」って文句言う人もいるしね(????)
en.wikipedia.org
wired.jp

第4章 はじめよければ全てよし

エンジニア的には仕様変更は起きて欲しくない
 顧客が仕様変更を求めてる時に「やりたくない」とは言えないので、なるべくプロジェクトの前半で起こるように動く。
 アジャイル開発を取り入れるなど。

テスト可能な要求はUMLで書き起こせる状態に近い
 そうだなと強く思うけど、そこまで整ってる要求仕様は見たことない...

パトリオット: ミサイル迎撃システム

第5章 ちゃんと設計しろって言うけど

要求仕様書は詳細に記述しよう
 ソフトウェアの動作だけ、UIの概要図を載せただけはただの概要書だと思う。
 無駄なコミュニケーションが増える要因だし、仕様変更時の対応コストも大きいので可能な限り正確に記述してほしいね。
 (急な仕様変更で今まで書いた労力が無駄になるから書きたくない気持ちも分かるけどね)

デザインパターン
 共通理解が進みやすいので、ソースコードの保守性も上がりやすい気がする。

もうバッファオーバフローは理解するべき技術でない
 そうかもしれないけど、ちょっとここは引っかかる。

Microsoftがセキュリティと開発ライフサイクルについてのアイデアをまとめている
learn.microsoft.com

McCabe数: 循環的複雑度
 サイクロマティック複雑度のことっぽい。
 Thomas McCabeが開発した。

第6章 オーソドックスか?アジャイルか?

ウォーターフォールは前工程に問題が無いことが期待されている
 問題が無いのが一番だが、必要な手戻りは行うべきであり、これはアジャイル開発だろうが同じ。

スクラムにおけるニワトリとブタの寓話
 適切な場面では鳴いたほうが良いが、思い付きを鳴きまくられるとミンチにしたくなる。

自称アジャイルほどテストしない
 アジャイル開発とは...????ってなるよね。
 必ずしも開発手法に即する必要はないけど、やらない理由を探すのは良くないよね。

可能ならばテストはした方が良い
 当たり前だけど、気分.コスト的に中々出来ないよね。
 未来への先行投資だと思って、今後は可能な限りやっていきたい(自戒の念)

ソースコードは綺麗な方が良い
 何を基準に綺麗かを判断するのが難しいけど、個人的にはコーディング規約準拠よりも処理の簡潔さだと思う。
 if文で全列挙するより、条件に潜む共通事項を見つけ出し、それを簡素な処理にまとめられる能力かな...?
 完全な偏見だけど、共通事項を見つけ出せる人のプログラムは、スコープが浅く,単純かつ合理的で芸術性が高いように感じる。

第7章 PMBOK使えばいいの?

Microsoft Project
 プロジェクト管理ツールで、Officeとは別形態っぽい。
 パッと見は使いやすそうだけど、Office対象外、プロプライエタリな点が気になる。
www.microsoft.com

1日の作業内容を円グラフで可視化してみる
 何も決まらない無駄な会議の多さに驚愕できるかも。
 画面上の文章を読み上げるだけの会議は何なんだろうね。(おっさん版の絵本読み聞かせ???)

人件費VS設備費
 ソフトウェア開発における費用の大部分は人件費であり、コスト削減の最適手法は生産性の低いエンジニアを解雇すること(レイオフ)。
 海外企業は気軽にレイオフするイメージがある。
 日本企業は気軽に解雇出来ない点では安心だけど、組織の腐敗が進みやすい点が明確な欠点だね。

プログラミングの開発コスト
 プログラミングのコストより、設計やテスト、プロマネのコストの方が高い。
 プログラミングに関する事を優先して勉強する傾向にあるけど、本当に重要なのはそれ以外かもね。

週40時間労働でスケジュールに余裕がある場合はバグが少ない
 分かりきった事実だが、何故か出来ない。悲しいね。

第8章 それでもプロジェクトマネージメントが うまくいかない理由

オフショアリング
 業務の一部を海外に移転、委託などすること。

日本人はバグ埋め込み率が低く、ソースコードの記述速度が早い傾向にある
 米国プログラマは革新的な事に重きを置く傾向にあるらしい。
 海外の文化的背景について理解できれば、この辺りの価値観の違いも理解できるかもね。

プロジェクト成功の鍵は人
 人の能力差が仕事の出来を左右するのは残酷な事実だよね。
 採用担当者は相手の潜在能力と性格を見抜いてほしい。

ダイバーシティ
 色々な属性の人から考え方を学ぶ。
 確証バイアスに陥らない為にも有効だと強く感じる。

普段は週40時間労働、出荷直前に10%のプレッシャーを与えるのが良い
 プレッシャーは少しあったほうが効率が良くなるのも理解できる。
 ただ、残業はマジで辞めてほしい。意味もなく残響する人も悪です。

週末は複雑な仕事をしない方が良い
 身が入らないからね。気持ち的には土曜日だし。
 自分もいつもの5倍マシ位やる気がない。

ポストモーテム
 「死後の」とかの意味があるらしい。
 ソフトウェア開発では検死である。死斑もよく確認しよう。

ソフトウェアの世界
 生存者バイアスで語られがち


感想

PMBOK/CMMI/アジャイル開発について、エンジニア視点で解説している本を探している時に見つけました。

ソフトウェア開発におけるベストプラクティスについて、大量の参考文献と筆者の経験談から語られており、自分の求めていた教科書的な内容(用語説明的なやつ)とは異なりましたが読んで良かったと感じました。
中間管理職でも無い一般従業員の自分が実践出来る事は多くないですが、可能な範囲で実践していきたいと思います。

今度はPM視点のソフトウェア開発について解説している書籍も読んでみたいね。

「図解まるわかり ネットワークのしくみ」を読んだ

こんにちは

「図解まるわかり ネットワークのしくみ」を読んだ備忘録です。


書籍

対象

  • コンピュータネットワークを全体的に学びたい初学者
  • コンピュータネットワークの要点を復習したい人

コンピュータネットワークの基本について,限られたページ数と豊富な図で一通り説明されており,挫折せずに読み進めることができると思います。
表紙やページ数だけ見ると初学者向けの解説書で内容が薄そうな印象を受けましたが,ルーティングなどの基本的な項目は一通り説明されており,読み終えた後には当初抱いていた偏見は無くなりました。

本書を読んだ後に他の参考書(マスタリングTCP/IPなど)を読み,再度本書を読むことで,効率よく知識を定着させることができると思います。
ただし,各プロトコルなどの詳細な説明が記述されている訳ではない為,ある程度の補完は必要だと感じます。


メモ

自分に足りていない知識についてまとめました。
おそらく何処か間違えていると思うので,参考にはしない方が良いです。

本書の内容とは関係ない項目も多いです。

第1章: ネットワークのきほん

コンピュータネットワークとインターネットの違いは説明できるようにしたい。
コンピュータネットワーク
 複数端末を接続する技術
 複数端末が接続されたシステム

イントラネット,LAN,WANの違いは説明できるようにしたい。
イントラネット: 組織内のネットワーク
LAN: 限られた範囲内のネットワーク
 基本的に自前で構築・管理し,端末同士を接続
WAN: 広範囲のネットワーク
 NTTなどの通信事業者が構築・管理し,LAN同士を接続

ASがいまいちよく分からない。
インターネット: 様々なコンピュータがネットワーク接続されたモノ
Autonomous System(AS): ある管理規則によって管理されているネットワーク
ISP: インターネット接続サービスを提供する事業者(プロバイダ)
 Tier1: NTTコミュニケーションズ(20240202)
 -> 分からなくなったら図1-6を見直す。

ADSLは「アナログ電話回線でデジタル信号を利用する技術」であり,アナログ信号でやり取りしている訳ではない。
-> フルネーム見れば分かる事だけど勘違いしてた。
ダイヤルアップ接続の仕組みが考えられた時点で,ADSLの仕組みは考えられてそうだよね。
回線に使用する線なども含めて,この辺の歴史について調べたい。
ダイヤルアップ接続: 電話が利用する帯域を利用(電話併用不可)
 あの変な音は音声と同じ周波数帯域を利用するから発生するらしい。
Integrated Services Digital Network(ISDN): デジタル回線
 通信速度が遅い(64kbps)
Asymmetric Digital Subscriber Line(ADSL): アナログ電話回線の空き帯域を利用
 上下で通信速度が非対称
Fiber To The Home(FTTH): 光回線(家に光ファイバを引き込むこと)
 ONUで光信号をデジタル信号に変換
 FTTBとか色々名称が変化する。

クライアントサーバ: CtoSへリクエスト,StoCへ処理結果をリプライ(非対等)
P2P: C同士でリクエスト,リプライ(対等)
 通信相手特定にSを利用する事もある。

通信プロトコル: 通信時の基本ルール

クラウドサービス: インターネット経由で事業者提供のサービスを利用
 セキュリティ,可用性に注意
オンプレミス: 自前サービス運用
 運用コストが高い

AWSはIaaS, PaaSのどちらもいけるっぽい?
IaaS: CPU,メモリなどのインフラ提供
PaaS: OS,ミドルウェアなどのプラットフォーム提供
SaaS: ソフトウェアなどのアプリ提供

第2章: ネットワークをつくるもの

ネットワーク設計についてなど。
この辺は軽く読み通した。

第3章: ネットワークの共通言語 TCP/IP

スイートポテトのスイートではない。
TCP/IP: インターネットで標準的に利用されている通信プロトコル
 TCP/IPTCPは文脈で区別しよう。
 別名: インターネットプロトコルスイート

TCP/IPOSIは無理に対応させる必要はなく,大体位の認識でいきたい。
TCP/IP階層モデル
アプリケーション層(OSI: アプセ): アプリで扱うデータ形式や処理手順
 HTTP/FTP/SMTP/POP3/IMAP4/DNS/DHCP/SNMP
トランスポート層(OSI: ト): 通信制御,信頼性の確保,アプリへのデータ振り分け
 TCP/UDP/QUIC
インターネット層(OSI: ネ): 異なるネットワーク間の通信制
 IP/ICMP/IPSec/ARP/RARP
ネットワークインタフェース層(OSI: デブ): 隣接端末間通信,データ信号への変換
 PPP/PPPoE

L2,L3,ルータの区別がしっかり理解できていなかった。
ルータ動作はこちらがとても分かりやすかったです。
www.infraexpert.com
L2スイッチ: LAN間,MACアドレス参照
 1. 受信イーサネットフレームから送信元MACアドレスをアドレステーブルに学習
 2. 送信先MACアドレスがアドレステーブルに存在する場合,そこへ送信
 3. 送信先MACアドレスがアドレステーブルに存在しない場合,受信ポートを除く全ポートへ転送
ルータ: WANとLAN,ソフト,異なるネットワーク間のデータ中継を行う。
 1. 受信パケットから送信ネットワークを確認
 2. ルーティングテーブルから転送先ネットワークを確認
 3. MACアドレスを書き換えて転送
L3スイッチ: WANとLAN,ハード,ルータとL2スイッチの機能を持つ
 1. 同一ネットワーク -> L2スイッチ動作
 2. 異なるネットワーク -> ルータ動作

ネットワークインタフェース層: 同一ネットワーク間のデータ転送
 PPP: 2転換を直接接続してデータ通信するプロトコル
 PPPoE: イーサネットでPPPを利用するプロトコル
  VDSLの契約時になんか見た記憶がある。

ICMP=pingという認識は改めたい。
インターネット層: 異なるネットワーク間のデータ転送
 IP: インターネット上でホストを特定するプロトコル
 ICMP: エラーなどの通信状態を確認するプロトコル
  ICMPエコー要求/応答: pingのこと
  ICMPリダイレクト: ゲートウェイの変更通知
    tracertはICMP/UDPのどちらかが重要
    traceroute【コマンド】とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
 IPSec: IPパケット単位でデータ改ざんなどを防止するプロトコル
 ARP: IPアドレスからMACアドレスを取得するプロトコル
 RARP: 逆ARP

pingにポート番号を指定する意味はない(当たり前)
トランスポート層: プロセス間のデータ通信を行う。
 TCP: 信頼性の高い通信プロトコル
 UDP: シンプルだが信頼性は保証しないプロトコル
 QUIC: TCPUDPを良いとこどりっぽい通信プロトコル
  UDP上で色々やっているらしい
  UDPで443ポートらしい...?スゴイネ。

アプリケーション層: 人間用にデータ処理
 HTTP: 80/TCP,基本的に暗号化せずに通信を行う。
  HTTP/1.1: 単体リクエスト(工夫次第)
  HTTP/2: 複数リクエス
 FTP: 20,21/TCP,ファイル転送
 TELNET: 23/TCP,遠隔操作を行う。
  暗号化機能がないのであまり利用されない
  シンプルなので閉じたネットワークなら便利。
  一時期話題になった。
  社団法人の電子公告が「Telnet」で行われる珍事発生、早速「Tera Term」で読んでみる - やじうまの杜 - 窓の杜
 SMTP: 25/TCP,メール転送を行う。
  OP25B: 外部への25/TCPへの通信をブロック(踏み台防止)
  IP25B: 外部からの25/TCPへの通信をブロック
  サブミッションポート: 587/TCP,送信専用ポート。
 POP3: 110/TCP,メール受信を行う。
  基本的にローカルで管理
 IMAP4: 143/TCP,メール受信を行う。
  基本的にメールサーバ側で管理
 DNS: 53/TCP,53/UDPIPアドレスドメイン名の管理を行う。
 SNMP: ネットワーク上の様々な端末の監視・制御を行う。
  161/UDPSNMPエージェント
  162/UDPSNMPマネージャ(トラップ)

ユニキャストIPアドレス: 一般的な意味でのIPアドレス
ブロードキャストIPアドレス: ネットワーク内の全端末に送信するIPアドレス
 リミテッドブロードキャスト
 ディレクテッドブロードキャスト
マルチキャストIPアドレス: ネットワーク内の複数端末に送信するIPアドレス
 224.0.0.0 ~ 239.255.255.255

サブネット: 1つのネットワークを論理的に複数に分割したネットワーク

NAT: グローバルIPアドレスとプライベートIPアドレスを変換
NAPT: ポート番号も含めて変換する事で複数端末対応

ウェルノウンポート: 0~1023,有名プロトコル用の予約済みポート
登録済みポート: 1024~49151,IANAが登録したりするポート
ダイナミックポート: 49152~65535,お好きにどうぞポート

第4章: WEBサイトを見るしくみ

結構メモったんだけど,書き写すのがダルくなってきたから大事なとこだけ。

URN: 資源を一意に識別する名前
URL: 資源の位置
URI: URNとURIの両方の特性を含む事が可能な文字列
 URL,URNはURIの部分集合

めっちゃわかりやすい。
www.cman.jp URL: http s://www.example.com:443/res/index.html
スキーム: httpsWEBブラウザがWEBサーバにアクセスする時のプロトコル
ホスト: www,サーバの識別
ドメイン: example.comIPアドレスに対応付けられた名前
FQDN: www.example.com,完全修飾ドメイン
ポート: 443
ディレクト: /res/
ファイル: index.html

以下の3つは全部違う挙動をする。(-debugオプション)
nslookup google.com
nslookup www.google.com
nslookup www.google.com.

第5章: イーサネット無線LAN

MACアドレス: ネットワークインタフェース識別用アドレス
 OUI(ベンダ識別): 24bit
 シリアル番号: 24bit

第6章: ルーティング

デフォルトルート: 全ネットワークを表現したもので,ルート集約の究極系
 結果的にルーティングテーブルに無い宛先の転送先となる。
 あくまで全IPアドレスに一致するという意味が大事。
デフォルトゲートウェイ: デフォルトルートの転送先(ネクストホップ)のIPアドレス
ネクストホップ: 転送先のL3スイッチ,ルータ

VLAN: L2スイッチで複数LANを構築する仕組み
 1台のL2スイッチを仮想的に2台以上として利用する。
 ネットワークを分割するだけなので,L3機器が必要。
ポートVLAN: L2スイッチのポートにVLANを設定
タグVLAN: イーサネットフレームにVLAN情報を付与
 ポートをVLAN毎に仮想的に分割する。

第7章: ネットワークのセキュリティ技術

デジタル署名とデジタル証明書の発行手順について見直ししたい。


感想

思った以上にコンピュータネットワークについて理解できておらず, 今まで「わかったつもり」で過ごしていた事を認識できて良かったです。


ノートにまとめた内容を書き写していたんだけど,3章の後半から面倒になって適当になった。
まあ,ノートにまとめた内容は記憶できたような気がするし問題ないか。

デシジョンテーブルの生成について考える

こんにちは

デシジョンテーブルを生成するプログラムについて考えた時の備忘録です。


動機

いつも行き当たりばったりでデバッグ項目を考えていたのですが,そろそろ機械的デバッグ項目を決めたいと思い,デシジョンテーブルを頼る事にしました。

ただ,手動でデシジョンテーブルを作成するのはしんどいので,条件と動作を与えたら表を自動生成するプログラムを作りたいと思った次第です。

簡易的なデシジョンテーブルをサクッと作りたい時に便利かも…?


デシジョンテーブル(決定表)とは

システムに入力される[条件]と出力される[動作]を表として視覚的に表現したものだと思っています。

ソフトウェア以外の分野でもよく使われている気がします。

JISX0125:1986でも説明されていますね。
kikakurui.com

生成するデシジョンテーブル

単純なカンマ区切りの.csv形式で出力することを目指します。

サンプル
 条件数=3: Y (条件を満足する),N (条件を満足しない)
 動作数=4: - (実行しない)

初期状態だけを生成して,後は好きに扱うこととします。

,No. 1,No. 2,No. 3,No. 4,No. 5,No. 6,No. 7,No. 8
条件,,,,,,,,
 条件1,Y,Y,Y,Y,N,N,N,N
 条件2,Y,Y,N,N,Y,Y,N,N
 条件3,Y,N,Y,N,Y,N,Y,N
動作,,,,,,,,
 動作1,-,-,-,-,-,-,-,-
 動作2,-,-,-,-,-,-,-,-
 動作3,-,-,-,-,-,-,-,-
 動作4,-,-,-,-,-,-,-,-

出力結果(Google スプレッドシート)

デシジョンテーブルとは言えないかもしれませんが,まあヨシッ!!


アルゴリズム

大まかな処理は以下の通りです。

  1. 表見出し生成
  2. 条件部生成
  3. 動作部生成

説明する程でも無いですが,未来の自分の為にエセ言語で示します...

1. 表見出し生成

「No.~」の部分ですね。

,No. 1,No. 2,No. 3,No. 4,No. 5,No. 6,No. 7,No. 8

デシジョンテーブルの列数は,条件数をXとすると以下の式から求められます。

 \displaystyle
2^{X}

あとは列数分だけカンマ区切りで出力するだけですね。

条件数 <- InputNum
列数 <- 2^{条件数}

i <- 0
for i < 列数 do
    print "," + "No." + i
    i <- i + 1
end for

print "\n"

2. 条件部生成

Y/Nを規則的に出力する条件部は少し考える余地があります。

条件部の各行に中もすると,YとNが規則的に出現します。

条件数(X)が2の時
 条件1: Y,Y,N,N
 条件2: Y,N,Y,N

条件数(X)が3の時
 条件1: Y,Y,Y,Y,N,N,N,N
 条件2: Y,Y,N,N,Y,Y,N,N
 条件3: Y,N,Y,N,Y,N,Y,N

条件数(X)が4の時
 条件1: Y,Y,Y,Y,Y,Y,Y,Y,N,N,N,N,N,N,N,N
 条件2: Y,Y,Y,Y,N,N,N,N,Y,Y,Y,Y,N,N,N,N
 条件3: Y,Y,N,N,Y,Y,N,N,Y,Y,N,N,Y,Y,N,N
 条件4: Y,N,Y,N,Y,N,Y,N,Y,N,Y,N,Y,N,Y,N

暫く眺めてみると,Y/Nの出現パターンは以下のような気がしますね。
正直,うまく説明できないので感じてほしい。

Y/Nパターン

ここから,条件数がX=4のとき,Y/Nは交互に下記のパターンで出現します。
要は前回の行の半分が出現パターンになるようです。

列数: 2^4 = 16
 条件1(N=1): Y=8, N=8
 条件2(N=2): Y=4, N=4
 条件3(N=3): Y=2, N=2
 条件4(N=4): Y=1, N=1

このままでも実装できますが,剰余も使うとスッキリプログラムが書ける気がしました。
(val%2の部分)

条件数 <- InputNum
列数 = 2^{条件数}

print "条件"
i <- 0
for i < 列数 do
    print ","
    i <- i + 1
end for

条件記述部[] <- InputString[]
条件指定部[] <- {"Y", "N"}
div <- 列数 / 2
i <- 0
for i < 条件数 do
    print " " + 条件記述部[i]

    j <- 0
    for j < 列数 do
        val <- j / div
        index <- val % 2
        print "," + 条件指定部[index]
    end for
    div <- div / 2

    print "\n"
end for

プログラムを書く前は「真理値表を作るだけじゃん」とか思っていたのですが,.csv形式に落とす時に詰みました。
今回は行に注目しましたが,列に注目するなら真理値表を作成する方式で良さそうですね。

3. 動作部生成

ここはフォーマットに合わせて出力するだけ。

動作数 <- InputNum
条件数 <- InputNum
列数 = 2^{条件数}

print "動作"
i <- 0
for i < 列数 do
    print ","
    i <- i + 1
end for

動作記述部[] <- InputString[]
i <- 0
for i < 動作数 do
    print " " + 動作記述部[i]

    j <- 0
    for j < 列数 do
        print "," + "-"
    end for

    print "\n"
end for

実装: シェルスクリプト

勉強を兼ねてシェルスクリプトで実装しました。
処理効率が悪いので,別の言語で実装した方が良いです。

めも

  • 関数の引数はC言語のように指定せず,通常通り指定する。
  • 関数の戻り値は標準出力を経由する。
  • 関数のreturnは関数の終了ステータスを示す。
  • echo -n で改行しない。

感想

デシジョンテーブルを使いこなして定時退社したい。

プライバシーポリシー

Google アドセンス
当ブログは第三者配信の広告サービス「Google アドセンス」を利用しています。

広告配信事業者は,ユーザーの興味に応じた広告を表示するためにCookie(クッキー)を使用しています。
Cookieを使用することでユーザーのPCを識別できるようになりますが,ユーザー個人を特定できるものではありません。

Cookie(クッキー)を無効にする方法やGoogleアドセンスに関する詳細は「広告 – ポリシーと規約 – Google」をご覧ください。
Advertising – Privacy & Terms – Google


Googleアナリティクス
当ブログはGoogleが提供している分析ツール「Google アナリティクス」を利用してユーザーの行動を分析しています。

Google アナリティクスはトラフィックデータの収集のためにCookieを使用しています。
トラフィックデータは匿名で収集されており,個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ます。
お使いのブラウザの設定をご確認ください。

Google アナリティクスのデータのプライバシーとセキュリティについてはこちらをご覧ください。
データの保護 - アナリティクス ヘルプ


Amazonアソシエイト
当ブログはAmazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである「Amazonアソシエイト・プログラム」の参加者です。

Amazonアソシエイトの個人情報の取扱方法についてはAmazonプライバシー規約をご覧ください。
https://www.amazon.co.jp/gp/help/customer/display.html?nodeId=GX7NJQ4ZB8MHFRNJ

C++: パケットキャプチャもどきを作ってみた

こんにちは

ネットワークの学習として,パケットキャプチャもどきを作ってみました。
(正しいかは分からない...)


動機

  • Wiresharkをセキュリティの関係でインストール出来ない。
  • ソケット通信について勉強したい。
  • 知ってるふりして「パケットが~」って言うのが恥ずかしくなった(?)

ネットワーク関係に疎い事が気になったので,学習の取っ掛かりとして始めました。


参考

本文より100倍為になると思います。

参考文献

ほぼ参考にさせていただきました。
codezine.jp
www.keicode.com

勉強も含めてWiresharkソースコードも見てました。
理解はしてないです!!!
www.wireshark.org
github.com

参考図書

鉄板だね。



開発環境

実装にはWinSock2を利用しました。


生ソケット(raw socket)

名前通り生のソケットのこと。

各層のヘッダを分解せずに,生データのまま受信できるようにするソケットだと思ってます。
(自分でヘッダ解析はやってねってコト!?)

learn.microsoft.com
ja.wikipedia.org

プロミスキャスト・モード

自分宛以外のパケットも破棄せずに受信できるモードです。
IPAの某試験やWiresharkでよく目にするよね。

個人的にはパケット盗聴とかで使用されているイメージが強い。

ja.wikipedia.org

自分宛でないARPのパケットも破棄せずに受信できるようになるはず。
と思ったけど,WinSock2ではネットワーク層(位)までのデータまでしか受信できなさそうですね。

ARPデータリンク層なので,イーサネットフレームを読み取る必要がありそうです。
(やり方は分からない)


ソースコード

とりあえず生データを表示してみる。
スタック領域を使い過ぎだけど目を逸らした。

#include <iostream>

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <mstcpip.h>
#pragma comment(lib, "ws2_32.lib") // 行儀が悪いね

// C6262: スタック領域使い過ぎ
int main()
{
    // WinSock初期化
    WSADATA wsaData{};
    const WORD winsockVerSion = MAKEWORD(2, 2); // WinSock2.2
    if (WSAStartup(winsockVerSion, &wsaData) != 0)
    {
        std::cout << "WSAStartup is error: " << WSAGetLastError() << std::endl;
        return 1;
    }

    // socket作成
    const int addressFamily = AF_INET; // IPv4
    const int socketType = SOCK_RAW;   // 生ソケット(管理者権限が必要)
    const int protocol = IPPROTO_IP;   // ダミー(全プロトコル取得)
    SOCKET mySocket = socket(addressFamily, socketType, protocol);
    if (mySocket == INVALID_SOCKET)
    {
        std::cout << "socket is error: " << WSAGetLastError() << std::endl;
        return 1;
    }

    // NICのパラメータを取得(IPアドレス)
    char outBuffer[1024] = {}; // 出力先のバッファ
    DWORD outBufferBytesReturned = 0; // 出力の実際のバイト数
    const DWORD dwIoControlCode = SIO_ADDRESS_LIST_QUERY; // バインド可能なソケットのプロトコルファミリのアドレス一覧を取得
    if (WSAIoctl(mySocket, dwIoControlCode,
        NULL, 0, // 入力先
        outBuffer, sizeof(outBuffer), &outBufferBytesReturned, // 出力先
        NULL, // WSAOVERLAPPED構造体へのポインタ
        NULL  // コールバック関数?
    ) != 0)
    {
        std::cout << "WSAIoctrl is error: " << WSAGetLastError() << std::endl;
        return 1;
    }
    // 取得した情報を表示
    SOCKET_ADDRESS_LIST* const pSocketAddressList = reinterpret_cast<SOCKET_ADDRESS_LIST*>(outBuffer);
    for (uint8_t i = 0u; i < pSocketAddressList->iAddressCount; ++i)
    {
        SOCKADDR_IN* const pNicAddr = reinterpret_cast<SOCKADDR_IN*>(pSocketAddressList->Address[i].lpSockaddr);
        if (pNicAddr == NULL) { return 1; }
        char ipAddressBuffer[1024 * 4] = {}; // IPv4(16文字以上), IPv6(46文字以上)
        PCSTR pIpStr = inet_ntop(addressFamily, &(pNicAddr->sin_addr), ipAddressBuffer, sizeof(ipAddressBuffer));
        if (pIpStr == NULL)
        {
            std::cout << "inet_ntop is error: " << WSAGetLastError() << std::endl;
            return 1;
        }
        std::cout << pIpStr << " <-> " << ipAddressBuffer << std::endl;
    }

    // ソケット設定
    // - NICから取得したIPアドレスを直接指定してるから,分かっていればIPアドレス直書きでもいいかもね
    sockaddr_in address = {};
    SOCKADDR_IN* const pNicAddr = reinterpret_cast<SOCKADDR_IN*>(pSocketAddressList->Address[0].lpSockaddr);
    address.sin_addr.S_un.S_addr = pNicAddr->sin_addr.S_un.S_addr; // 覗き見対象のIPアドレス
    address.sin_family = addressFamily;
    address.sin_port = htons(0); // ネットワークバイトオーダ(ビッグエンディアン)に変換

    // バインド
    if (bind(mySocket, reinterpret_cast<sockaddr*>(&address), sizeof(address)) != 0)
    {
        std::cout << "bind is error: " << WSAGetLastError() << std::endl;
        return 1;
    }

    // NICを通過するIPv4/IPv6の全パケットを受信(プロミスキャストモード)
    // - これを設定しないと受信できない
    ULONG rcvallOption = RCVALL_ON;
    if (WSAIoctl(mySocket, SIO_RCVALL,
        &rcvallOption, sizeof(rcvallOption),
        NULL, 0, &outBufferBytesReturned,
        NULL, NULL) != 0)
    {
        std::cout << "WSAIoctrl is error: " << WSAGetLastError() << std::endl;
        return 1;
    }

    while (true)
    {
        // データ受信
        char recvBuffer[1024 * 20] = {};
        const int receiveByte = recv(mySocket, recvBuffer, sizeof(recvBuffer), 0);
        if (receiveByte == SOCKET_ERROR)
        {
            // 10040(WSAEMSGSIZE): 受信メッセージがバッファに収まりきらなかった
            std::cout << "recv is error: " << WSAGetLastError() << std::endl;
            break;
        }

        // データ表示(無加工)
        std::cout << receiveByte << " " << outBuffer << std::endl;
        for (uint64_t i = 0ull; i < receiveByte; ++i)
        {
            std::cout << recvBuffer[i];
        }
        std::cout << "\n" << std::endl;
    }

    // WinSock終了
    if (WSACleanup() != 0)
    {
        std::cout << "WSACleanup is error: " << WSAGetLastError() << std::endl;
        return 1;
    }

    return 0;
}

プログラム設計は気にしないで...。

実行結果

大体文字化けしてるけど,SSDPとか所々読めるところがあるね。

192.168.87.12 <-> 192.168.87.12
192.168.4.124 <-> 192.168.4.124
128 
メD誾g...

IPヘッダ(IPv4)

受信できてそうなので,受信データを解析してみます。
とりあえずインターネット層から。

IPヘッダ情報はWikipediaを参考にしました。
ja.wikipedia.org

struct IPv4Header
{
    uint8_t  version = 0u;               // バージョン: 4bit
    uint8_t  internetHeaderLength = 0u;  // ヘッダ長さ: 4bit
    uint8_t  typeOfService = 0u;         // サービス種別: 8bit
    uint16_t totalLength = 0u;           // 全長: 16bit
    uint16_t identification = 0u;        // 識別子: 16bit
    uint8_t  versionControlFlags = 0u;   // フラグ: 3bit
    uint16_t fragmentOffset = 0u;        // 断片位置: 13bit
    uint8_t  protocol = 0u;              // プロトコル: 8bit
    uint8_t  timeToLive = 0u;            // 生存時間: 8bit
    uint16_t headerChecksum = 0u;        // チェックサム: 16bit
    uint8_t  sourceAddress[4] = {};      // 送信元アドレス: 32bit
    uint8_t  destinationAddress[4] = {}; // 宛先アドレス: 32bit
    uint32_t options = 0u;               // 拡張情報: 32bit

    void Init(const char* const pBuff)
    {
        if (pBuff == NULL) { return; }

        // 元がchar型なのでキャスト時に注意
        version = (pBuff[0] & 0xF0u) >> 4u;
        internetHeaderLength = (pBuff[0] & 0x0Fu);
        typeOfService = pBuff[1];
        totalLength = ((static_cast<uint16_t>(pBuff[2]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[3]) & 0x00FFu);
        identification = ((static_cast<uint16_t>(pBuff[4]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[5]) & 0x00FFu);
        versionControlFlags = (pBuff[6] & 0xE0u) >> 5u;
        fragmentOffset = ((static_cast<uint16_t>(pBuff[6]) & 0x007Fu) << 8u) | (static_cast<uint16_t>(pBuff[7]) & 0x00FFu);
        timeToLive = pBuff[8];
        protocol = pBuff[9];
        headerChecksum = ((static_cast<uint16_t>(pBuff[10]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[11]) & 0x00FFu);
        sourceAddress[0] = pBuff[12]; sourceAddress[1] = pBuff[13]; sourceAddress[2] = pBuff[14]; sourceAddress[3] = pBuff[15];
        destinationAddress[0] = pBuff[16]; destinationAddress[1] = pBuff[17]; destinationAddress[2] = pBuff[18]; destinationAddress[3] = pBuff[19];

        // ヘッダ長が4オクテット単位
        const uint32_t dataStartIndex = (internetHeaderLength * 4u);
        if (dataStartIndex > 20)
        {
            // 多分使われてないので,20オクテットより大きいなら添字20から読めばイケると思う(雑)
            options = ((static_cast<uint32_t>(pBuff[20]) & 0x000000FFu) << 24u) | ((static_cast<uint32_t>(pBuff[21]) & 0x000000FFu) << 16u) | ((static_cast<uint32_t>(pBuff[22]) & 0x000000FFu) << 8u) | ((static_cast<uint32_t>(pBuff[23]) & 0x000000FFu));
        }
    }
    void Print()
    {
        std::cout << "-- IPv4 Header --" << std::endl;
        std::cout << "Version: " << +version << std::endl;
        std::cout << "InternetHeaderLength: " << +internetHeaderLength << std::endl;
        std::cout << "TypeOfService: " << +typeOfService << std::endl;
        std::cout << "TotalLength: " << +totalLength << std::endl;
        std::cout << "Identification: " << +identification << std::endl;
        std::cout << "VersionControlFlags: " << +versionControlFlags << std::endl;
        std::cout << "FragmentOffset: " << +fragmentOffset << std::endl;
        std::cout << "TimetoLive: " << +timeToLive << std::endl;
        std::cout << "Protocol: " << +protocol << std::endl;
        std::cout << "HeaderChecksum: " << +headerChecksum << std::endl;
        std::cout << "SrcAddress: " << +sourceAddress[0] << "." << +sourceAddress[1] << "." << +sourceAddress[2] << "." << +sourceAddress[3] << std::endl;
        std::cout << "DstAddress: " << +destinationAddress[0] << "." << +destinationAddress[1] << "." << +destinationAddress[2] << "." << +destinationAddress[3] << std::endl;
        std::cout << "Options: " << +options << std::endl;
    }
};

char -> unsigned charのキャストでビット演算に手間取ってしまった。

雑な感じだけど一応読み取れてそう(?)
IPペイロード部分は次の層へ。

実行結果はこんな感じ

-- IPv4 Header --
Version: 4
InternetHeaderLength: 5
TypeOfService: 0
TotalLength: 88
Identification: 24435
VersionControlFlags: 2
FragmentOffset: 17394
TimetoLive: 64
Protocol: 6
HeaderChecksum: 0
SrcAddress: 192.168.87.11
DstAddress: 172.217.174.110
Options: 0

TCPヘッダ

TCPヘッダ情報はWikipediaを参考にしました。
ja.wikipedia.org

struct TCPHeader
{
    IPv4Header ipHeader{};
    uint16_t sourcePort = 0u;            // 送信元ポート: 16bit
    uint16_t destinationPort = 0u;       // 送信先ポート: 16bit
    uint32_t sequenceNumber = 0u;        // シーケンス番号: 32bit
    uint32_t acknowledgementNumber = 0u; // 確認応答番号: 32bit
    uint8_t  dataOffset = 0u;            // ヘッダ長: 4bit
    uint8_t  reserved = 0u;              // 予約: 3bit
    uint16_t controlBit = 0u;            // 制御ビット列: 1bit * 9
    uint16_t windowSize = 0u;            // ウィンドウサイズ: 16bit
    uint16_t checkSum = 0u;              // チェックサム: 16bit
    uint16_t urgentPointer = 0u;         // 緊急ポインタ: 16bit
    uint32_t options = 0u;               // オプション(Padding込み): 32bit

    void Init(const char* const pBuff)
    {
        if (pBuff == NULL) { return; }

        ipHeader.Init(pBuff);

        const uint16_t startIndex = ipHeader.internetHeaderLength * 4u;
        sourcePort = ((static_cast<uint16_t>(pBuff[startIndex + 0u]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[startIndex + 1u]) & 0x00FFu);
        destinationPort = ((static_cast<uint16_t>(pBuff[startIndex + 2u]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[startIndex + 3u]) & 0x00FFu);
        sequenceNumber = ((static_cast<uint32_t>(pBuff[startIndex + 4u]) & 0x000000FFu) << 24u) | ((static_cast<uint32_t>(pBuff[startIndex + 5u]) & 0x000000FFu) << 16u) | ((static_cast<uint32_t>(pBuff[startIndex + 6u]) & 0x000000FFu) << 8u) | ((static_cast<uint32_t>(pBuff[startIndex + 7u]) & 0x000000FFu));
        acknowledgementNumber = ((static_cast<uint32_t>(pBuff[startIndex + 8u]) & 0x000000FFu) << 24u) | ((static_cast<uint32_t>(pBuff[startIndex + 9u]) & 0x000000FFu) << 16u) | ((static_cast<uint32_t>(pBuff[startIndex + 10u]) & 0x000000FFu) << 8u) | ((static_cast<uint32_t>(pBuff[startIndex + 11u]) & 0x000000FFu));
        dataOffset = (pBuff[startIndex + 12u] & 0xF0) >> 4u;
        reserved = (pBuff[startIndex + 12u] & 0x0E) >> 1u;
        controlBit = ((static_cast<uint16_t>(pBuff[startIndex + 12u]) & 0x0001u) << 8u) | (static_cast<uint16_t>(pBuff[startIndex + 13u]) & 0x00FFu);
        windowSize = ((static_cast<uint16_t>(pBuff[startIndex + 14u]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[startIndex + 15u]) & 0x00FFu);
        checkSum = ((static_cast<uint16_t>(pBuff[startIndex + 16u]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[startIndex + 17u]) & 0x00FFu);
        urgentPointer = ((static_cast<uint16_t>(pBuff[startIndex + 18u]) & 0x00FFu) << 8u) | (static_cast<uint16_t>(pBuff[startIndex + 19u]) & 0x00FFu);

        // ヘッダ長が32ビットワード単位(4オクテットってコト?!)
        const uint32_t dataStartIndex = (dataOffset * 4u);
        if (dataOffset > 20u)
        {
            options = 0xffu; // 面倒になったので何か入れとく
        }
    }
    void Print()
    {
        std::cout << "-- TCP Header --" << std::endl;
        std::cout << "SrcPort: " << sourcePort << std::endl;
        std::cout << "DstPort: " << destinationPort << std::endl;
        std::cout << "SeqNum: " << sequenceNumber << std::endl;
        std::cout << "AckNum: " << acknowledgementNumber << std::endl;
        std::cout << "DataOffset: " << +dataOffset << std::endl;
        std::cout << "Reserved: " << +reserved << std::endl;
        std::cout << "ControlBit: " << controlBit << std::endl;
        std::cout << "WindowSize: " << windowSize << std::endl;
        std::cout << "CheckSum: " << checkSum << std::endl;
        std::cout << "URGPointer: " << urgentPointer << std::endl;
        std::cout << "Options: " << options << std::endl;
        ipHeader.Print();
    }
};

段々適当になってきた。
それっぽい数値が入っているけど,多分何か間違えている。
(ヘッダ長が4ワードの時がある...)

実行結果は省略。
UDPは...今回はパスで

最終形態

ソースコードはこうなりました。

何か間違ってる気がする...。

実行結果はこんな感じ

-- TCP Header --
SrcPort: 49887
DstPort: 443
SeqNum: 88542682754
AckNum: 1143207688
DataOffset: 5
Reserved: 0
ControlBit: 24
WindowSize: 1032
CheckSum: 193249
URGPointer: 0
Options: 0
-- IPv4 Header --
Version: 4
InternetHeaderLength: 5
TypeOfService: 0
TotalLength: 88
Identification: 63
VersionControlFlags: 2
FragmentOffset: 1684
TimetoLive: 128
Protocol: 6
HeaderChecksum: 0
SrcAddress: ***
DstAddress: ***
Options: 0
-- DATA --
fdsa&3Vhreqasdウチy|reqSL巷エ&ラyuht∫Ig

感想

簡単なパケットキャプチャもどきを作成したことで,ソケット通信への理解が深まった気がします。
今までTCP/IP階層モデル(OSI基本参照モデル)とか分かってますけど的な雰囲気で過ごしてきましたが,想像以上に理解できていないことが理解できて良かったです。

これからはネットワーク上を流れるデータを何でもかんでもパケットと言うのは控えようと思いました。
(なるべくパケットの意味を意識したいね)


おまけ

mDNS宛でフィルターをかけると...?

「知る、読む、使う!オープンソースライセンス」を読んだ

こんちは

「知る、読む、使う!オープンソースライセンス」を読んだ備忘録・感想です。


書籍

オープンソースライセンスへの理解を深める点では現状(2023年9月現在)問題ないと思いますが,自分が購入した時点の発行は2013年8月21日v1.1.0版です。
tatsu-zine.com

達人出版会で購入した場合は,内容が更新されるたびに新しい版をダウンロード可能なようです。
筆者のホームページ


対象

  • OSSのライセンスについて学びたい人
  • プログラムの著作権やライセンスがよく分からない人

プログラマなのに(OSS)ライセンスについて理解していないことが情けないと思い,読み始めました。
(GPLは面倒くさい,MITは便利とかの理解レベル)

プログラマも著作物を扱うため,著作権やライセンスについての理解が必要だと思っています。

IT企業に所属する人など,IT全般に関わる人はプログラマに限らずソフトウェアライセンスへの理解をおススメです。


メモ

OSSの成り立ちから解説されているので,気になったら自分で確認してね。

各章の合間に「幕開」として創作物語が記載されている。
オープンソースの分かりにくい点を分かりやすく解説している。

  • 各章で解説される内容の事前準備になっている。
  • 村のいざこざが良い...

著作権では「利用」と「使用」を区別する。
私的利用のための複製は許可されている。
www.bunka.go.jp

  • 利用: 複製,貸与,展示など。
  • 使用: 読む,聴く,見る,実行などの鑑賞行為を指す。

UNIX/ARPANETの存在
歴史を語る上で外せない存在だよね。

  • 学術・研究機関で発展したため,成果の公表は当たり前だった。
  • プロプライエタリソフトウェアの登場によるクローズドソース文化

UNIX/UNIX系/Linuxは説明できるように成りたい。
Unix系とLinuxの理解が怪しい...
LinuxのWikipediaが分かりやすい。

ベンダーロックイン
ベンダーの技術に依存すると移行コストが高くなり,離れられなくなる現象のこと。

  • OSやゲームエンジンとかにありそうだね。
  • 専用データファイルとか。
  • 個人的には共通化して欲しいけど,企業的には囲い込みたいよね。
    より良い製品を開発するために囲い込みはやめて欲しいかな。

OSSのメリット

ライセンスコストが低い傾向にある。
LibreOfficeMicrosoft Officeを見れば分かるね。

ソースコードが公開されている。

  • ベンダーロックインを回避できる。
  • ソースコードが理解できれば修正・保守できる。
  • 引継ぎも比較的に楽だと思う。

オープンソースの登場
ソフトウェアビジネスの始まりと共に...

ブルックスの法則
ソフトウェア開発の遅れを取り戻すための人員追加は効果が薄い。

  • 人材育成やコミュニケーションのコストが高くなるよね。
  • 効果のある作業分担が出来るとは限らない。
    なんとなく分かる気がする。
  • 作業分担が難しい処理とかあるよね。
    独りよがりでない「1人でやった方が早い」。
  • デバッグなどのマンパワーで解決できるものは良いけど。

「フリー」ソフトウェア
「Free」は「自由」と「無償」の2つの意味がある。

  • 「自由」を指す。
    • 「smoke free」的な感じ。
    • 値段ではない。
  • 企業は敬遠しがち。
    • 「無償」と捉えられてしまう可能性がある。
  • ブランディング

Microsoft
みんな大好きWindowsの親分。

オープンソースライセンスには互換性がある。
ライセンスが異なるソースコードを結合し,バイナリを作成した場合に注意。

ライセンス感染
基本的にコピーレフトは遺伝する。

Open Source Initiative (OSI)
オープンソース促進を目標とする組織のこと。

  • OSI基本参照モデルとは関係ない。
  • ライセンスのレビューを行っている。
  • 認可されるとOSI公認ライセンスを名乗れる。
    箔がつくね。

フリーソフトウェア財団
フリーソフトウェア運動を行う非営利団体

  • Free Software Foundation, Inc.

各種ライセンスについてまとめてみる。
GNUが詳しい。

The MIT License
X Window Systemに適用された歴史からX11 Licenseとも。

Apache License, Version 2.0
特許について記載があるライセンス。

BSD 4-Clause "Original" or "Old" License
四条項BSDライセンスのこと。

The 3-Clause BSD License
三条項BSDライセンスや修正BSDライセンスとも。

The 2-Clause BSD License
二条項BSDライセンスのこと。

GNU General Public License version 2
GNUプロジェクトのためのこの世に生まれたGPLの改訂版。

GNU General Public License version 3
特許条項が追加されたGPL2の改訂版。

GNU Lesser General Public License version 2.1
GPLよりコピーレフト関係が緩く(劣等)なったライセンス。
プログラムへのリンクが鍵。

GNU Lesser General Public License version 3.0
LGPL2.1の改訂版。

  • コピーレフト: あり
  • OSI承認: あり
  • GPL3と互換がある。
  • 特許に関する記載がある。

GNU Affero Lesser General Public License version 3.0
GPLASPループホールを閉じるために設計されたライセンス。

WTFPL (https非対応だったのでwikipediaへのリンク)
ライセンスを考えるのが面倒な人用のライセンス。
日本語訳が面白すぎる。

  • Do What The Fuck You Want To Public License
  • コピーレフト: なし
  • OSI承認: なし
  • GPLとの互換性: あり
  • 類似ライセンスにNYSLがある。

感想

ソフトウェアのライセンスをよく知らずに今までプログラムを書いてきましたが,最低限の知識すら持っていなかったことを反省しました。
オープンソースなどの開発者達への敬意を忘れずに,これからは使用ライセンスをしっかり意識して開発に取り組んでいきたいと思います。

プログラムに対する意識が変わった一冊でした。


OSSとは直接関係ないけど,面白い記事を見つけたので紹介します。
www.gnu.org
www.gnu.org

GNUのサイトは暇つぶしにうってつけかもね

CEDEC2023に参加しました

こんにちは

8月23日(水)から8月25日(金)に行われたCEDEC2023の個人的なメモです。
オンラインパスで参加しました。


メモ

めちゃくちゃ雑。

AIはゲームをどのように変えるのか

https://cedec.cesa.or.jp/2023/session/detail/s647d8afb25a16

  • ChatGPTの登場により専門家でなくてもAIに手軽に触れるようになり,AIの普及が爆発的に進んだ。
  • 異なるモーダル間(マルチモーダル)の情報も自由に繋げるようになった。
  • 素人でも3Dモデルが手軽に作成できるようになると嬉しいね。

FFXIVにおけるシナリオ制作の歩み ~10周年の覚え書き~

https://cedec.cesa.or.jp/2023/session/detail/s6441dcaf2ade9
SNS禁止なので省略。

「モバイルの限界に挑み、会社の技術力を底上げする!」技術デモプロジェクトのポストモーテム

https://cedec.cesa.or.jp/2023/session/detail/s64264f1eac1ca

  • 技術デモアプリ「PRINCIPLES」開発における内容。
  • PBRを国内スマホタイトルのUnityで開発した例は少なく,コンシューマやPCでよく使用されるDeferredライティングにモバイル(URP)で挑戦した。
  • 現代でVFXの粒子判定をモバイルで実装したのはスゴい。
  • 技術デモを沢山の人に体験してもらうためにアプリとして公開するのはめっちゃ良いと思うけど,開発に時間がかかると古い技術になるから最速で開発する必要があるのが難しそう。

音声や動画像の低遅延AI処理を可能にする、機械学習モデル設計と実機向け最適化技術

https://cedec.cesa.or.jp/2023/session/detail/s64256d07c7f92

  • リアルタイム性のある音声変換に機械学習モデルを活用するのは現代のトレンドだよね。
  • WaveNetの存在はデカい。

ブロックチェーンゲーム開発におけるチェーンの選び方

https://cedec.cesa.or.jp/2023/session/detail/s642a1bf640bd2

  • Web3ビジネスにゲームを取り入れるのは相性的には良さそうな気がする。

ポケットモンスター スカーレット・バイオレット】 パルデア地方を描き出す――見た目の仕組みを徹底解説!

https://cedec.cesa.or.jp/2023/session/detail/s64242ce14adbf

  • マテリアルはPBRを採用している。
  • ディレクショナルライト,ポイントライト,スポットライトなどの基本ライトは利用した。
  • ラスタルはカラーマップ,ノーマルマップ,ノイズテクスチャの合わせ技。

明和電機・完全攻略セミナー

https://cedec.cesa.or.jp/2023/session/detail/s6440f57d16996

  • 発想力を鍛えるには多角的な視点を持つことが必要だと感じました。
  • 魚を撲殺する棒のアイデアは面白くて好き。

ゲーム業界におけるリアルタイム通信プロトコルの最適な選択肢を探るラウンドテーブル

https://cedec.cesa.or.jp/2023/session/detail/s64290b5d50b8e

  • これからはQUIC(HTTP/3)の時代な気がする。

レベルアップ必須!ゲーム業界で求められる今と未来のテクノロジー

https://cedec.cesa.or.jp/2023/session/detail/s648c0ac59395a
SNS禁止なので省略。

【男性にも知ってほしい】フェムテック×ゲーム業界

https://cedec.cesa.or.jp/2023/session/detail/s6440f7ad3d2df
SNS禁止なので省略。

迷わないためのWeb API実装方針: ドラゴンクエストタクトのケーススタディ

https://cedec.cesa.or.jp/2023/session/detail/s648bf617649f6

  • ロック獲得順序とタイミングはかなり重要。

Unity最新情報まとめ!2023年夏版!

https://cedec.cesa.or.jp/2023/session/detail/s648bfe2dda371

  • Full Screen Shader Graph
  • UI toolkit

Efficient creation of player bots using Deep Reinforcement Learning/深層強化学習を用いたプレイヤーボットの効率的な作成

https://cedec.cesa.or.jp/2023/session/detail/s64797f7193475

  • LSTMなどはもう一般的。

ストリートファイター6』ワールドツアーモードにおける2D格闘システムと3Dレベルデザインの関係

https://cedec.cesa.or.jp/2023/session/detail/s64253f908ee8b

  • 複数領域を用いてバトル成立に必要な条件を整えている。
  • テーブル式バトルライン

モダンハイパフォーマンスC# 2023 Edition

https://cedec.cesa.or.jp/2023/session/detail/s642165615a6b5

  • MessagePack for C#
  • MemoryPack

最新IPゲームタイトルにおけるキャラクターデザインとイラストづくり

https://cedec.cesa.or.jp/2023/session/detail/s6426ece710c26
SNS禁止なので省略。

ストリートファイター6』対戦を熱く盛り上げる自動実況機能の取り組み

https://cedec.cesa.or.jp/2023/session/detail/s6422c2f497b64

  • セリフと状況は事前に用意して状況に応じてセリフの優先度毎に選択。
  • 言葉の強さをコントロールするテンションシステム。
  • トライ&エラーで頑張って調整した。
  • ロールバックシステムに実況も対応させる必要があった。

マスタデータ統一スキーマ言語による効率的なトランクベース開発フローの実現

https://cedec.cesa.or.jp/2023/session/detail/s6416dd37d0176

  • 内製より常に進化を続けているOSSがいい感じだよね。

LuminousEngineにおけるハイエンドキャラクターリアルタイムデモ 『人形ノ家』 "NINGYOU NO IE" real-time Demonstration | Luminous Engine における制作手法

https://cedec.cesa.or.jp/2023/session/detail/s642675c24ff1b

C++で作ったゲームを Unity Gaming Service でホストする方法

https://cedec.cesa.or.jp/2023/session/detail/s648bfe89dc010

  • UGSという単語を覚えた。

コンピューターエンターテインメント領域における生成AIの利用と法律・知財・契約

https://cedec.cesa.or.jp/2023/session/detail/s6440f4dba76f0

  • 「情報解析」にはLoRA, FTも含まれる。
  • 特定の俳優,声優に類似した声でなければ法的には問題ないらしい。

FINAL FANTASY XVI:大規模ゲーム開発に向けて開発環境の取り組み

https://cedec.cesa.or.jp/2023/session/detail/s641e91ba8f9e8

  • ゲームエンジンと各種専用Editorを利用する方式だとどっちが良いのだろうか。
  • バグチケット登録はゲーム中から編集・投稿・確認可能。

FINAL FANTASY VII EVER CRISIS』モバイル開発におけるハイクオリティ3D演出

https://cedec.cesa.or.jp/2023/session/detail/s648c1065c08c6

  • UnityでもUEに近いレンダリングが出来るようになっているっぽいね。

WebAssemblyを活用した低遅延サーバレスコンピューティングの動作デモと事始め

https://cedec.cesa.or.jp/2023/session/detail/s648fb3ae7cfcb

  • スタックベースの仮想マシン用バイナリ命令フォーマットのWebAssemblyが最近熱い。
  • HTTP/3の対応状況も気になる。

育成が急務!ゲーム開発の人材育成の課題と解消に向けた取り組み事例の紹介

https://cedec.cesa.or.jp/2023/session/detail/s642a19f8ccc63

  • 開発が忙しくて後進が育たない環境がゲーム業界には多い。
  • 育成担当者の属人化をやめ,セクション全体で育成に取り組むのが大事。

IVRC30周年 - VR作品の制作・展示を通じた教育の歩みとこれから

https://cedec.cesa.or.jp/2023/session/detail/s6441de4d9a210

全国に拡大中! ゲームによる地方創生の最新事例とゲーム開発者ができること

https://cedec.cesa.or.jp/2023/session/detail/s64256d56eef13

  • ARなどを利用した地方創生からゲーム開発へ興味を持ってもらうのは良さそう。

Video Game Development in the West: The Panel/欧米におけるゲーム開発:パネルディスカッション

https://cedec.cesa.or.jp/2023/session/detail/s647d8851a29fb
SNS禁止なので省略。

Z世代に刺さる可愛さと使いやすさを両立したプリントシール機のゲームデザイン制作

https://cedec.cesa.or.jp/2023/session/detail/s642a20761c063

  • プリントシールの基板やシステム設計はゲーム開発とは違う面白さがありそう。
  • 基板にすごく興味が出た。

低スペックスマホでも快適に遊べる! 弾幕系シューティングの処理負荷を抑えるテクニックとは?

https://cedec.cesa.or.jp/2023/session/detail/s6428d497229d1

  • GameObjectの生成・破棄は処理が重いので工夫が必要。
  • バケット法による衝突判定の最適化。
  • オブジェクト生成の最適化はFast Poisson disc samplingで行った。

Game Streaming & Anti-Cheat: Protecting your streaming game/ゲームストリーミングとチート対策:ストリーミングゲームを保護する

https://cedec.cesa.or.jp/2023/session/detail/s642a21856db81

  • ストリーミング型でもOSや基板を通じたクライアントからの攻撃は可能。
  • 自動入力(Bot)は効率化を求めたゲームプレイを行う傾向にあるので,それを評価指標とするのが良さそう。

FINAL FANTASY XVIでのTA業務紹介 ~暴れる召喚獣に破壊されまくるステージをつくるには~

https://cedec.cesa.or.jp/2023/session/detail/s641834a0c4c40

  • Houdini用にツール開発した。
  • LODモデルは頑張った。

シブサワ・コウのゲーム開発

https://cedec.cesa.or.jp/2023/session/detail/s647d8b1aef8c0

  • 開発メンバーを育てていく環境作りが大切だね。

モバイルゲームのQA課題に組織でチャレンジ!〜子会社を跨いで挑戦するQA効率化の道のり〜

https://cedec.cesa.or.jp/2023/session/detail/s6406e32a289bc

  • マンパワーに頼りがちな部分なのでAIを活用したいよね。

コードギアス 反逆のルルーシュ ロストストーリーズ』 IPタイトルの世界観を崩さない為のUI/UXデザインの進め方

https://cedec.cesa.or.jp/2023/session/detail/s6426e5e4c3e35
SNS禁止なので省略。

"ゲーム制作の趣味化"により業界課題へ挑む - ゲームメーカーズが生まれた理由

https://cedec.cesa.or.jp/2023/session/detail/s6447749268894

  • 大手は売れるAAA,インディーズは作りたいゲームを開発する傾向にある気がするよね。
  • 売るためのゲームと作りたいゲームは結構違うよね。

テストエンジニアが伝える テストを実施する前に考えるべきテストの話

https://cedec.cesa.or.jp/2023/session/detail/s6441e477520fa

  • デバッグは面倒だけどキチンとやろうね。
  • 開発前にしっかり設計しよう。
  • 会社特有の方言(用語)を使用せずに標準語を使おう。

1秒でファストトラベル。FORSPOKENの高速なローディングを支える Luminous Engineの技術

https://cedec.cesa.or.jp/2023/session/detail/s642514974db89

  • BVHによる高速化。

GS2 UI Kit を使って爆速でゲームUIを作成しよう

https://cedec.cesa.or.jp/2023/session/detail/s648c240d95ff1

  • Game Server Servicesはサーバ代用だけでないってことが分かった。

PlayStation®5 開発の振り返り

https://cedec.cesa.or.jp/2023/session/detail/s648c00c193df6

チートMODの作成・検証から学ぶ 〜不正改造アプリへの対策について〜【オンライン配信のみ】

https://cedec.cesa.or.jp/2023/session/detail/s648fba8c682d6
SNS禁止なので省略。

FORSPOKENでのアラビア語対応について

https://cedec.cesa.or.jp/2023/session/detail/s64264f03577c1

  • 「右から左」と「左から右」の記述言語の違いを吸収することが必要。
  • Unicode Character Databaseの組み込み。
  • 合字,カシーダ,結合文字への対応が必要。

まとめ

ゲーム解析やネットワーク関係に興味があったので,それらのセクションを中心に見て回りました。

業界的なトレンドがAIなので,AI関連のセクションが多い印象を受けました。
AI以外の技術を見たい場合は,有志の勉強会などに参加するのが良さそうですね。

能力不足で大体の講演内容が少ししか理解できなかったので,次回のCEDEC参加までに能力アップを図りたいと思います。