2023 年 1 月のこと

ただの忘備録的な日記です。

WiFi ルーター

数年愛用していた I/O データのルーターが逝ったため、とりあえず最寄りの家電量販店で同メーカーのミッドゾーン?くらいのルーターを購入。

しかし、これが。。。

業務的な案件は別にして、LAN 内の特定のマシンの IP を固定して使いたい場合、DHCP 固定割当という機能を使うのが一番楽だと思う。

私は(少なくとも自宅では)ずっとこのやり方で通してきたのだが、購入した I/Oデータの WiFi ルータに搭載されていなかった。

いや、でも、これだとネットワークプリンタの類にデータ送れなくないか?

解せぬ。

逆にエレコムのものは全ての機種に搭載されていた。

結局、交換してもらった。

値段は少々落ちたので、通信の安定性などに影響出るかと思ったが、エレコムの方がめちゃくちゃ安定している。

I/O データ、バッファロー、エレコムあたりの企業がどういう基準で競争しているのかわからんが、これだけ品質に差があるともう今後しばらくは I/O データの製品は買えない。

カプリコーン杯 2023

今年のカプ杯は、中京芝1200m 。

高松宮記念モチーフの久々の短距離チャンミとなった。

結果を先に書いておくと、サークルの主要なメンバーは全員グレード A の決勝進出

サークルのメンバーのほとんどが社会人で構成され、育成もそんなに頑張ったわけではないのに(なにしろ時間がない)、これは凄いんでないかい?

特に、ゲーム関係のチャット部屋で盛り上がっていたのは、某氏の育成した差バンブーメモリー。

今回のチャンミは、迫る影(直線一気)が加速スキルとしてかなり有効とみられていたため、脚質的には

先行>追い込み>逃げ>>>>差し

とされていた。

だから、後方脚質勢は、追い込み運用が多かったと思う。
バンブー自体もたまに遭遇したが、ほとんどが追い込みだったと記憶している。

なんで、差で、しかもさほど強キャラとはされていないバンブーで勝率いいのかみんな不思議に思い、かつ驚愕していたわけだ。

では、なぜ差バンブーで勝てていたのか?

この観点からトレーナーさんの発言をまとめる。

バンブー自体は、正月ガチャでお迎えできた時から、コミカルな感じに好感を持っていた。

試しに育成すると意外に固有が出やすい。

エースはドロワーフジキセキに決めていたが、その直前にたまたま賢さネイチャを完凸にできたので、これを活かして差を1個体は育成しようと考えていた。

バンブーは魔改造しなくても短距離走れるので、キャラ選択はさほど迷わなかった。

ただし、初期に育成した個体は弱かった。

強行策積んだ追い込みに中盤では追い越されていた。

固有スキルはそこそこは強いが、スピードがノッた追い込みを差し返せるほどではない。

そこで、中盤位置あげスキルを意識して取るようにした。

位置取り押し上げは有効だが、これだけだと弱いので、正月サトノダイヤモンド固有を必ず継承させた。

あとは試行回数。

他の2個体はほとんど育成も考えず、開催期間中もほぼバンブーだけ育成した。

この育成方針は参考になるところがいくつもある。

短距離だったとはいえ、ようつべやツィあたりで言われている常識的な育成方法が絶対ではないことをよく表している。

決勝でもこのトレーナー、あっといわせるレース展開に持ち込んだんだが、動画あげてくれないかな?

coreData

Mac での ORM といったら coreData だが、obj-c のコマンドラインアプリプロジェクトで coreData を使おうとするとなぜか swift のファイルが生成されてしまう

ここは勘違い。codegen するとき、以下の箇所で objective-C を指定する。

 

 

 

 

 

ORM と infinite recursion の問題

これまで、hiberante などの ORM を使ったサンプルコードで双方向の関係を取り上げなかった理由は、いわゆる infinite recursion (無限循環)の問題にけっこう悩まされるから。

このサイトでは、対象を初学者〜中級者に想定しているが、おそらくそういった層に infinite recursion に関係するバグが発生しかねないサンプルを掲げたら、混乱は必至でしょう。

それで、意識的に避けてました。

無限循環は大抵の場合、<親-子-孫-・・・> の関係があるときに発生する。

つまり、親-子が1対多であるときだ。

この場合、例えば、hibernate であれば、親側の子を示す変数(データベースではカラム)に @OneToMany のアノテーションをつけ、子側に親の当該変数を指し示す変数に @ManyToOne のアノテーションを付与する。

教科書的にはこれで双方向の関係が定義できたことにはなる。

何も問題なさそうじゃないか?という声が聞こえてきそうだが、実際には困った挙動を示すことがある。

子のオブジェクトを生成し、これを JSON などで表示したいときに、当然、親側の情報も持っているから、ORM はこれを引っ張ってくる。
ところが、親は子の情報も持っているから、そこから子の情報を探そうとする。
探しだされた子は、さらに親の情報を取り出そうとして・・・

と、立派な無限循環が完成してしまう(笑)。

具体的にはこういうやつ↓です。


Infinite recursion (StackOverflowError)
(through reference chain: model.Parent["child"]
->org.hibernate.collection.spi.PersistentBag[0]
->model.Child["parent"]->model.Parent["child"]
->org.hibernate.collection.spi.PersistentBag[0]
->model.Child["parent"]->model.Parent["child"]
->org.hibernate.collection.spi.PersistentBag[0]
->model.Child["parent"]->model.Parent["child"]
->org.hibernate.collection.spi.PersistentBag[0]
->model.Child["parent"]->model.Parent["child"]
以下、無限に続く。。。(笑...えない)

使い慣れた ORM であれば、どこら辺が危険かある程度わかっているから、経験的に回避できなくもないが、仕様もうろ覚えのような ORM ではひとたびこの問題が発生したらハマること必至でしょう。

意識的に避けてきた理由はそこにある。

特に初学者に人は、まず習得したい ORM がどう動作しているか視覚的にわかるようなところから始めるといいと思う。

以前に Person – Phone の例を挙げたとき、person_phone などという一見邪魔くさいテーブルが生成されたが、わからなくなったら意識的にああいうテーブルをつくったらいいと思う。

遠いようでいて速いと思う。

 

参考

こことか。探せばいくらでも出てきそう。

コメント返し

コメントにこういうのがあった。
なんか、私の近くにいそうな人(ツィ友?)のような気もするが…。

>双方向はバグの温床となる気がするので、片方向だけでなんとかするというアプローチはありでしょうか?

ううむ。
やってやれなくはないので、そうしても構わないと思います。システム構築が大変だと思いますが。
ですが、無限循環が問題になるのはキケンな関係にあるクラス(のインスタンス)をダイレクトに参照しようとするときです。

実用的には、こういった直接参照を使わないということでもいいと思います。

具体的には、表示したいオブジェクトがあるときは、まず、その上流のオブジェクトにアクセスし、ゲッターで本当に操作したいオブジェクトを取得する、みたいなやり方です。

あるいは @JsonIgnore あたりのアノテーションを駆使するとか。

循環参照への対策

Resourceクラス(JavaBean)をJSONやXML形式にシリアライズする際に、相互参照関係のオブジェクトをプロパティに保持していると、循環参照となりStackOverflowErrorやOutOfMemoryErrorなどが発生するので、注意が必要である。

循環参照を回避するためには、

Jacksonを使用してJSON形式にシリアライズする場合は、シリアライズ対象から除外するプロパティに@com.fasterxml.jackson.annotation.JsonIgnoreアノテーション

JAXBを使用してXML形式にシリアライズする場合は、シリアライズ対象から除外するプロパティにjakarta.xml.bind.annotation.XmlTransientアノテーション

を付与すればよい。
https://terasolunaorg.github.io/guideline/current/ja/ArchitectureInDetail/WebServiceDetail/REST.html 

この手のアノテーションは便利だとは思います。
ですが、これらを多用すると可読性が落ちる気がしますし、仕様が変わってしまえば「動かない」コードになってしまいがちです。

システムならなんでもそうだと思いますが、基本設計をなるべくシンプルにして、どうしようもないところは(姑息的になるかもしれませんが)ワザを繰り出していくというのがワイの基本ポリシーです。

今回のネタに関して言えば、ここぞというところでは双方向も使っていいんじゃないでしょうか。

(追記)
ORM には循環参照がつきものと考えたため、この記事を起こしたのだが、全く循環参照を気にしなくていい便利 ORM も存在する。
このブログでも頻出の CoreData。
ライブラリ側でよしなにやってくれるようだ。
逆に絶対に意識してデータ構造を組まないとダメなのは、やはり hibernate。
ワイが注視していることプロジェクトがあるのだが、思いっきりコケそう。
convertor パターンを崩したら、その分、補償する必要があるのだが、通常のマッパーで代用効くのか?
しかし、このプロジェクト、第三者からの対応が下手くそすぎる。