[YMIR-299] PageクラスのBaseに古い名前のプロパティが残ってしまう Created: 2009-01-24  Updated: 2009-03-05  Resolved: 2009-03-05

Status: Closed
Project: Ymir
Component/s: ymir-extension
Affects Version/s: 1.0.0
Fix Version/s: 1.0.2

Type: Improvement Priority: Major
Reporter: jflute Assignee: skirnir
Resolution: Fixed Votes: 0
Labels: None


 Description   

【概要】
プロパティの名前を変更して、自動生成し直しても、
PageクラスのBaseに古い方の名前のプロパティ定義が残ってしまう。
すると、変わったことによる影響範囲がコンパイルエラーで現れないため、
ジェネレーションギャップのメリットが薄れてしまっている。
実際に古い方の名前のプロパティに対して処理が書かれたままで、
動かすと全く動かないでどこだろうと探してしまうことがあった。

【原因考察】
おそらく「PageクラスのBaseに手動でプロパティを追加できる」
という機能が影響してしまっているのではないかと考える。
手動で追加されたのか古くなって残っているかの区別がYmir側でできないかと。

【解決案】
しかしながら「PageクラスのBaseに手動で何かを追加できる」という
機能に関しては、YMIR-295にも書かれているが、実際の業務では
利用する場面はいまのところ想像できない。
利用しないで特に困らないならそのままでもよいが、
本課題のような不具合が発生してしまっているので対策がある方が良い。
「PageクラスのBaseに手動で何かを追加できる」という機能は、
デフォルトではOFFにしても良いかと考える。
(そうすることで古い名前のプロパティは消える)

SystemNotificationで、クラス毎に「スーパークラス手動追加OK」を
指定できるようにしてもいいかも。(デフォルトはOFFで)



 Comments   
Comment by skirnir [ 2009-03-05 ]

完了とします。

Comment by jflute [ 2009-03-05 ]

Pageクラスのプロパティ、DTOクラスのプロパティともに不要なプロパティは削除されることを確認しました。
また、二つの画面にまたがったプロパティも両方消したときに初めて削除されることを確認しました。

ありがとうございます!

Comment by skirnir [ 2009-03-05 ]

対処しました(r2896)。

Comment by jflute [ 2009-01-27 ]

議論の結果、
実装上細かいところで課題はあると思うが、
この方向で実装することになりました。

Comment by jflute [ 2009-01-26 ]

思いつきですが、提案ということで書いておきます。

PageクラスのBaseの各プロパティに、
「自分がどのHTMLから生成されたものなのか」
の情報を自動生成時に付与することで古いプロパティを判定する。

例えば、FooPage(foo.html)とBarPage(bar.html)とあるとします。
BarPageには、Bar自体のプロパティとFooからのプロパティが混在します。

BarPageのプロパティ例:
 Bar自体のプロパティ → Hoge
 Fooからのプロパティ → Fuga

この状態で最初に書いた「PageクラスのBaseは毎度全部上書き」
をやってしまうと、おっしゃる通りbar.htmlのBarの生成(更新)のときは、
Fugaが消えてしまい、foo.htmlからのBarの生成(更新)のときは、
Hogeが消えてしまいます。これではよくありません。

そこで、それぞれのプロパティに「自分の出身地」を付与します。

@Meta(from="bar.html")
public void setHoge() {
...

@Meta(from="foo.html")
public void setFuga() {
...

この情報を自動生成時に利用します。

Hogeプロパティをbar.htmlからを削除もしくは別の名前のプロパティにしたとします。
bar.htmlのBarの生成(更新)のとき、既に存在するBarPageBaseのプロパティの「出身地」を見て、
bar.htmlのもので、今回の生成(更新)でプロパティ対象とならないものは古いプロパティとして削除します。

万が一、複数出身地があったらあったで、「@Meta(from=

{"foo.html", "bar.html"}

)」と表現して、
"foo.html"から消えたら(foo.htmlでの生成)、「@Meta(from=

{"bar.html"}

)」に修正されて(出身を消す)、
"bar.html"から消えたら(bar.htmlでの生成)、完全に削除するでいいかなと思います。

このやり方だと、互換性が保つことができて、
「出身地」の情報がないもの、かつ、HTML上にいないプロパティは「手動で追加されたもの」と判断し、
消すことはしないようにすれば、以前の動きと変わらず古いプロパティが削除可能かと。
そして、これは単なる項目だけでなく、DTOやConverterなどにも応用できるかなと思います。

上記の例はあくまで例で「出身地の表現」や「アノテーション」は、
実装上の都合に合わせて変える必要はあると思いますが、
仕組みとしてこういうのはどうかなと思いました。

Comment by jflute [ 2009-01-25 ]

ご説明ありがとうございます。

> あるページクラスが複数のHTMLから生成されうるため
> この機能はうまく働かないことがあることが発覚
なるほど、こちらの件理解しました。
なんとも仕組み的に難しい問題ですね。

> この件はまずは「どのプロパティがどのプロパティに変更されたかを検出する方法」
自分も何か良い案が思いついたらコメントしますね。

あと、とりあえず今の時点では、古いのはBaseクラスの変数定義を手動削除して、
コンパイルエラーになったGetter/Setterなどをひたすら消していくという
やり方をExampleに書いておきますね。

ありがとうございます。

Comment by skirnir [ 2009-01-25 ]

これは不具合ではなく、どちらかというと仕様です。

プロパティ名を変更するような再生成をした場合、どのプロパティがどのプロパティに変更されたかを自動生成機構は(今のところ)知ることができません。そのため古いプロパティは残ってしまいます(DBFluteでも昔のEntity?クラスが残ってしまっていたのと似ています)。

これを避けるには、プロパティ変更の対応関係をどうにか検知するか、おっしゃるように「Baseクラスには手を入れてはいけない」というルールにするかどちらかだと思います。前者は今のところ困難なのでやるとしたら後者です。

ところが、実は以前この機能は存在していたんですが、あるページクラスが複数のHTMLから生成されうるためこの機能はうまく働かないことがあることが発覚し、安全のためこの機能が廃止されたという経緯があります。

具体的には、例えばedit.htmlにポストバックのformタグがあった場合、EditPageBaseが自動生成されますが、一方でlist.htmlにedit.html?id=XXXのような、edit.htmlへのリンクが存在する場合はlist.htmlに変更があった場合EditPageBaseが更新されてしまいます。この時、list.htmlに含まれるedit.htmlが持つ情報は不完全(edit.htmlのサブセット)であるため、Baseクラス差し替えとしてしまうと、edit.htmlの情報のうちlist.htmlに*含まれれない*情報が全て消えてしまうのです。

これを避けるには、やはりBaseクラスのマージ作業が必要となり、そうすると古いプロパティを残すか消すかの判定をしないといけなくなりますが、どのプロパティが「古い」のかの判定はできないので結局適切に処理ができないことになります。

ところでPageクラスのBaseに手動で何かを追加できるという機能は、主に2つの理由から存在します:

1. アノテーションを追加したいだけなのにSetterなどをオーバライドしないといけないのは面倒
2. プロパティの型を後で手動で変えたい場合にBaseをいじれないとどうしようもない

1は、久保さんのおっしゃるように、YMIR-295でアノテーションを透過的に扱えれば解消します。2は、自動生成画面で変えるというルールにすれば良いですし、どのみち再生成時はPageクラスとPageBaseクラスから型定義を読み取っているので、Baseが洗い換えされるようにしたとしても「Baseに書いた定義を手で変更する機能」を残しておいても問題は生じません。

発散してきましたが、この件はまずは「どのプロパティがどのプロパティに変更されたかを検出する方法」を考える方向で進めたいと思います。

Generated at Fri Apr 26 11:37:23 JST 2024 using Jira 9.15.0#9150000-sha1:9ead8528714127d8cfabf2446010d7e62c0a195c.