526 | | |
527 | | == Todo == |
528 | | * only Immutables and ProObjects concept |
529 | | * use properties, not fields; fields can be used, though in specific purposes if you know what you're doing. |
530 | | * findOne(), findAll(), ProUitl.getKey() |
531 | | * PropretyStatus - A state of a trackable object. |
| 526 | This is an example how the dependency graph between ProObjects should look. |
| 527 | * It should contain cycles, otherwise we can never initialize this graph. |
| 528 | * An Immutable shouldn't depend on anything. |
| 529 | * ProObjects could depend on other ProObjects and Immutables. |
| 530 | * The leafs of this acyclic graph should be Immutables. |
| 531 | |
| 532 | If a ProObject A depends by a Prop<X> P on some object X which doesn't depend on anything, then there are two cases: |
| 533 | * X is immutable. Then when someone changes P, it would be through P's interface so the ProLib can detect this change and A can get notified that X has changed. |
| 534 | * X is mutable and ProObject. X can change in two ways: |
| 535 | * A Property Q of X has changed. Then P would detect when X's Q changes and A would get notified about it. |
| 536 | * The same as the above but Q is a normal Java field. Well, nothing conventional can be done to detect when Q changes, so we're screwed, so '''don't use normal Java fields in ProObjects, unless you're sure what you're doing'''. |
| 537 | * X is mutable but is not a ProObject. In this case obviously nothing can be automatically done by the ProLib to detect when X changes. |
| 538 | |
| 539 | This means that you should follow the rules above in order to produce non-flawed ProLib code. In general you can use ProObject, Immutables and the rest is junk (: |
| 540 | |
| 541 | == ProLists, findOne(), findAll(), ProUtil.getKey() and ListEntry == |
| 542 | Let's have this case: |
| 543 | {{{ |
| 544 | ... |
| 545 | class Party implements ProObject { |
| 546 | public ListProp<Person> people() { ... } |
| 547 | |
| 548 | public ListProp<Person> invitedPeople() { |
| 549 | class invitedPeople extends AutoListProperty<Person> { |
| 550 | @Override |
| 551 | protected ProList<Person> constructList() { |
| 552 | return new ComposingProList<Person>() { |
| 553 | @Override |
| 554 | protected ProList<Person> computeData() { |
| 555 | ArrayList<Person> res = new ArrayList<Person>(); |
| 556 | for (Person person : people().get()) { |
| 557 | if (person.getName() == "Meddle") { |
| 558 | res.add(person); |
| 559 | } |
| 560 | }; |
| 561 | } |
| 562 | } |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | return getBean().makeProp(invitedPeople.class); |
| 567 | } |
| 568 | ... |
| 569 | }}} |
| 570 | |
| 571 | So, in this example you want to get the List of all invited people to your party, invite only people whose name is "Meddle" and update this list when a potential candidate to come to the party is added. This is kinda slow though, because each time a new Person is added to People, I don't want to reconstruct the whole invitedPeople list. |
559 | | * Inspector - A GUI tool that allows browsing the application state while it still works. |
560 | | |
561 | | == How to apply properties to Sophie 2.0 == |
562 | | * To convert mutable classes to ProObjects |
563 | | * To gather more requirements to the properties library and apply them |
564 | | * To keep the properties library with high quality, because everything else will depend on it. |
565 | | * To be careful of cyclic dependencies (like a = b + 1, b = a + 1). No library can solve them. |
| 599 | * Inspector - A GUI tool that allows browsing the application state while it's still working. |
| 600 | |
| 601 | == Good Practices == |
| 602 | * Use ProObject and Immutables when using the ProLib. The rest is junk. Although if you know what you're doing, you can find useful stuff in the junk (: |
| 603 | * Convert mutable classes to ProObjects. |
| 604 | * Keep the ProLib and with high quality, because everything else will depend on it. |
| 605 | * Be careful not to create cyclic dependencies (like a = b + 1, b = a + 1). No library can solve them. |