I just had this conversation with Rickard about the above which bothered me for
quite a while now:
WDYT ?
Michael
this pattern:
List<ContactRoleValue> contacts = state.contacts().get();
contacts.add(contact);
state.contacts().set(contacts);
why not use state.contacts()._().add(contact)
is otherwise the UoW EntityListener not notfied about changes?
ContactRoleValue is a Value, so needs to be explicitly set
Michael: 03 :51
its a list, isn't it?
Rickard: yes, but like you said, UoW doesn't get any callback if you just
update the list
Michael: ok
Rickard: I even think the List should be immutable actually
Michael: then I'd propose to get rid of the list/set/collection interfaces on
our assocs
Rickard: why???
assocs are mutable!
Michael: because you introduce a lot of accidental complexity with all those
methods you inherit from there
all we need is an : add, get, remove and interate
03:53
iterate
Rickard: but then you can't use them with libraries that takes collections!
Michael: and perhaps an toList/Collection
because if you expose all the collection interface methods you must also guarantee that no one uses them behind your
back to change the content of the list
and imho you cant guarantee that
we had a start of this discussion some time ago in qi4j
Rickard: ???
now I don't understand at all. The methods from ListAssociation are all ok to
use
Michael: but's exposing internal state and keeping all the contracts is quite
nasty
Rickard: sorry, not following...
what do you mean by "exposing internal state"?
Michael: ok, you have a bunch of objects in an assoc
the basic operations on that stuff that are really needed are the some i
mentioned above
Rickard: true
Michael: all the rest is syntactic sugar or compatibility
the problem is - is our assoc really a jdk collecition ? isn't it rather a
association between entities/values ?
Rickard: see your point. but are there any methods in List (for example) that
don't really make sense?
for assocs I Mean
Michael: and by exposing all the mutable methods to the outside you have to care for all the accesses that may mutate
your assoc even if you don't want that
what about immutable assocs ?
if you have an toList() you can just return an unmodifiableList(association())
but if you are a list yourself and want to be mutable you cant protect yourself
Rickard: but, note that ListAssociation<> at least as used in StreamFlow is
only available internally
I never expose ListAssociations directly in Entity interfaces
if you want to expose the ListAssociation, then do it as an Iterable<MyEntity>
and that should be fine
Michael: yes that was my first point about that
Rickard: or, as a Query
as Queries are immutable
if you define ListAssoc in your internal state, with access to all the collection methods, but only expose either domain
methods or Iterable<>/Query<> views of that assoc, what is the problem?
the argument that I might agree with is that there are methods in List that
don't make any sense on Associations
Michael: nice example (i hope)
remove(int i) in ListAssocInstance
Rickard: toArray, lastIndexOf, subList are a bit weird
for example
Michael: where does the notification/vetoing happen
as it only happens in remove(Object) of ManyAssocInstance
or iterator().remove() is (imho) also not reported to the listeners
Rickard: for remove(i) that's a bug
I forgot to add the vetoing in ListAssociationInstance
Michael: see what I mean ?
Rickard: same thing
not really. you found a bug
which is good!
Michael: it's quite hard to get it right if you expose all the nasty methods of
the collection classes
Rickard: but it's not inherent
hard, yes, but not inherent
Michael: but why do we normally encapsulate and delegate (prefer delegation to
inheritance) ?
Rickard: I'm looking for inherently bad reasons, not difficulty of
implementation
Michael: because if we inherit we inherit all the contracts of the superclass if we delegate we chose which
methods/contracts we expose to the outside world
Rickard: I agree, and so, again, what I am interested in is if there are methods in List which are bad from an
association point of view, not if they are hard to implement
if all the methods make sense, but are hard to implement, that's fine!
Michael: what about retainAll in ManyAssocInstance ?
is also not going along the votes
Rickard: so then the problem is: is that a bug that can be fixed, or is it
nonfixable?
Michael: sure they can be fixed but are they necessary in the first place
lets ask me the other way round
Rickard: you are using the wrong arguments my friend
Michael: whats the necessity of inheriting from the jdk collection classes ?
Rickard: finding bugs doesn't help
ok, good question
Michael: sure it helps one can fix them
Rickard: so, the main idea is to be able to use the manyassocs with libraries
that can use JDK collections, which are a lot
if we do our own, we are on our own also
Michael: but which you could also do if you expose an toCollection() method in
the manyassoc
which should then be immutable (imho)
Rickard: ok, can you explain the difference between these two approaches?
Michael: yes sure
Rickard: there doesn't seem to be a whole lot?
Michael: it is
Rickard: if you can, then I'm interested!!!
Michael: if I expose myself as an jdk collection class and am mutable
i have to deal with all the issues around mutability
if i expose my internal list as an unmodifiablecollection to the outside world I don't have to deal with mutability
issues from the jdk classes at all
and as I provide some (2) mutating methods on myself (add, remove) i have full
control there
so i define the interface that clients are able to use againts me rather than
having it dictated by some obscure josh bloch
it also makes testing much easier as there are only 2 contracts you have to
test for
and it also allows you to give stronger guarantees about your correctness
Rickard: ok
now you're making sense!
much better arguments
and if we add the toList/toSet etc. then I get my thing as well
Michael: I just looked at ListAssocInstance, with that an retainAll you will have much fun fixing those I did this some
time ago for some of my own stuff and I just dropped the collection exposure after that
yes
I didn't mean to cut us off the collection
but to control the access
especially if we care about notifications, voting, state handling etc
another interesting aspect
if I expose the jdk stuff in my classes how would I add an concern regarding
e.g. mutability or auditing ?
Rickard: good point again
Michael: if i want to have an audit log for all changes and don't want to specify all the necessary listeners (which can
be easily forgot) i just want to add one sideffect and be done
but if i have a plenthora of methods that mutate state and even some that are
not accessible
(or how would you write an sideffect for list.listIterator.set(object))
Rickard: very good point
alright. You have convinced me
with the toList/toSet as immutable variants I'm fine
Michael: retainAll is especially messy (have a look at the javadoc) - you have to perform the actual operation before
knowing whats in and whats out
I would volunteer to make those changes in qi4j
Rickard: write an email to the list with the suggestions, with arguments as
above
I'll +1 it
Michael: as I am guilty of convincing you and have done this already in other
projects
ok
may I just copy this communication?
Rickard: yup
Michael: and sorry for not starting with better arguments, its 4:30 am here
Rickard:
04: 28
no worries
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev