incubator-clerezza-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Henry Story <henry.st...@bblfish.net>
Subject Re: [jira] [Commented] (CLEREZZA-603) EzMGraph fails when working with more than one instance
Date Tue, 19 Jul 2011 15:17:24 GMT

On 19 Jul 2011, at 11:43, Reto Bachmann-Gmür wrote:

> I think it's important to identify anti-pattern. Post a link here if
> you document the anti-pattern you think you've discovered on the scala
> mailing list.

I asked the question on the Scala mailing list, here:

  https://groups.google.com/d/topic/scala-user/IsJ1yXjd2lw/discussion

There seems to be unanimous agreement that this is an ant-pattern. But I am trying
to make sure that your name is associated with it since you have been so insistent
on this point. Currently I am favoring the name"Pimpin Reto". Perhaps it will take on.


> As for the copying around triples I think we should work with unions
> and not copying around triples, changing this might have some impact
> on the api so I disagree in having the copy solution in trunk.
> 
> The example you describe as error-prone is unnecessarily calling
> methods on an explicit instance (see my comment on the issue:
> https://issues.apache.org/jira/browse/CLEREZZA-603?focusedCommentId=13063414&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13063414)
> this makes it verbose an error prone:
> 
> import ez1._
> //here we are working on the MGraph ez1
> b_("reto") -- FOAF.homepage --> "http://bblfish.net/".uri
> 
> import ez2._
> //here we are working on the MGraph ez2
> b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
> 
> Remeber that when we change bnode and b_ to return a GraphNode we need
> to add a dynamic conversion from GraphNode to Node to keep the
> existing functionality.
> 
> Reto
> 
> 
> On Tue, Jul 19, 2011 at 11:27 AM, Henry Story (JIRA) <jira@apache.org> wrote:
>> 
>>    [ https://issues.apache.org/jira/browse/CLEREZZA-603?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13067591#comment-13067591
]
>> 
>> Henry Story commented on CLEREZZA-603:
>> --------------------------------------
>> 
>> In that discussion I ended up explaining in detail why the current problem exists.
But in order
>> to understant the problem one has to first understand what is on in constructs such
as the following:
>> 
>>  reto.a(FOAF.Person)
>>          -- FOAF.knows --> (
>>                "http://bblfish.net/#hjs".uri.a(FOAF.Person)
>>                        -- FOAF.name --> "Henry Story"
>>                        -- FOAF.currentProject --> "http://webid.info/".uri
>>               )
>> 
>>  Starting from the center, let us see how implicits are getting used here:
>> 
>>  1.  "http://bblfish.net/#hjs".uri.a(FOAF.Person)
>> 
>>  a)   gets transformed into
>> 
>>        new URIRef("http://bblfish.net/#hjs")
>> 
>>     because the .uri method is defined on EzLiteral and there is the
>>     implicit def string2lit(str: String) = new EzLiteral(str)
>> 
>>  b)  then it gets transformed into a RichGraphNode - let's call it anon_rgn_hjs -
because the method a(..) is defined there and because of the implicit (call it IMP)
>> 
>>      implicit def toRichGraphNode(resource: Resource) = {
>>                new RichGraphNode(new GraphNode(resource, baseTc))
>>        }
>> 
>>  2. Then the RichGraphNode anon_rgn_hjs is filled out with the FOAF.name and FOAF.currentProject
relations
>> 
>>  3. reto - a rich graph node - is then related by foaf knows to anon_rgn_hjs.resource
>>       by the following function
>> 
>>                def -->(sub: GraphNode): RichGraphNode = {
>>                        //RichGraphNode.this + sub
>>                        -->(sub.getNode)
>>                }
>> 
>> 
>>   QUESTION: what happens to the graph of anon_rgn_hjs ? How does it get added to
the graph of reto?
>>   --------
>> 
>>  Well this occurs because of the implicit IMP  which this whole issue is questioning
the wisdom of,
>> 
>> 
>>     implicit def toRichGraphNode(resource: Resource) = {
>>                new RichGraphNode(new GraphNode(resource, baseTc))
>>     }
>> 
>>   Notice that the implicit created a new GraphNode, whose graph is called "baseTc".
But where does baseTc come from?
>> Ahah. IMP is part of a trait:
>> 
>> protected trait TcDependentConversions extends TcIndependentConversions {
>> 
>>        def baseTc: TripleCollection
>> 
>>        implicit def toRichGraphNode(resource: Resource) = {
>>                new RichGraphNode(new GraphNode(resource, baseTc))
>>        }
>> }
>> 
>> And  EzMGraph is defined as extending that trait.
>> 
>>    class EzMGraph(val baseTc: MGraph) extends AbstractMGraph with TcDependentConversions
>> 
>> 
>> putting it together:
>> -------------------
>> 
>> When you create a new EzMGraph - call it ez - you create an object with the toRichGraphNode()
implicit, whose baseTc set to that Graph's tc collection. The you
>> 
>>  import ez._
>> 
>> to import that implicit so that it becomes available for usage. Of course that implicit
is tightly tied to ez.
>> So this explains then how anon_rgn_hjs gets added to ez. It's because when in 1b
above when
>> new URIRef("http://bblfish.net/#hjs") was transformed into a RichGraphNode using
the IMP implicit, the
>> graph of ez was added as its backing store.
>> 
>> Ok so all that is really clever! But just a bit too clever by half, sadly.
>> 
>> Remember that the point of this patch is to fix the real problem with the current
framework, which is that
>> currently if you have two graphs you need to keep writing the import statements every
time you wish to
>> change graph. Like this:
>> 
>>  import ez1._
>>  ez1.b_("reto") -- FOAF.homepage --> "http://bblfish.net/".uri
>> 
>>  import ez2._
>>  ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
>> 
>>  import ez1._
>>  ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri
>> 
>> 
>> This is very error prone it seems to me.
>> 
>> And the reason we have that error, is because of the an implicit that is tied
>> to a hidden variable. This is very clearly a Scala anti-pattern.
>> 
>> 
>>> EzMGraph fails when working with more than one instance
>>> -------------------------------------------------------
>>> 
>>>                 Key: CLEREZZA-603
>>>                 URL: https://issues.apache.org/jira/browse/CLEREZZA-603
>>>             Project: Clerezza
>>>          Issue Type: Bug
>>>            Reporter: Henry Story
>>>            Priority: Critical
>>>         Attachments: 0001-CLEREZZA-603-EzMGraph.bnode-now-returns-a-RichGraphN.patch
>>> 
>>>   Original Estimate: 1h
>>>  Remaining Estimate: 1h
>>> 
>>> All the EzMGraph test cases currently assume that there is only one ez graph
available per method.
>>> When one adds two EzMGraphs together in some code one gets a failure as the following
test case shows when run in EzMGraphTest class:
>>>       @Test
>>>       def twographs {
>>>               val ez1 = new EzMGraph() {(
>>>                       b_("reto") -- FOAF.name --> "Reto Bachman-Gmür".lang("rm")
>>>               )}
>>>               Assert.assertEquals("the two graphs should be equal",1,ez1.size)
>>>               import ez1._
>>>               ez1.b_("reto") -- FOAF.homepage --> "http://bblfish.net/".uri
>>>               Assert.assertEquals("ez1 has grown by one",2,ez1.size)
>>>               //now a second graph
>>>               val ez2 = new EzMGraph() {(
>>>                       b_("hjs") -- FOAF.name --> "Henry Story"
>>>               )}
>>>               ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
>>>                //both of these tests fail
>>>               Assert.assertEquals("ez1 is the same size as it used to be",2,ez1.size)
>>>               Assert.assertEquals("ez2 has grown by one",2,ez2.size)
>>>       }
>>> This is caused by a bit too much implicit magic.  EzMGraph extends TcDependentConversions
which is defined as
>>> protected trait TcDependentConversions {
>>> 
>>>       def baseTc: TripleCollection
>>> 
>>>       implicit def toRichGraphNode(resource: Resource) = {
>>>               new RichGraphNode(new GraphNode(resource, baseTc))
>>>       }
>>> }
>>> So when developing this one has to import the toRichGraphNode method for the
TripleCollection one is using.
>>> Hence you will see the first
>>>               import ez1._
>>> above. The errors can be avoided if one enters a new import for ez2._ just before
code using ez2 . The problem is that this will never be picked up by the compiler and the
error will only be found at runtime. But then code would look like this
>>>               import ez1._
>>>               ez1.b_("reto") -- FOAF.homepage --> "http://bblfish.net/".uri
>>>                 import ez2._
>>>               ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
>>>               import ez1._
>>>                       ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri
>>> The answer to this problem is simply to have the ez1.b_ method return a RichGraphNode
directly containing the EzGraphNode from which it was called.
>>> It makes more sense anyway to have a Graph return a GraphNode when one asks for
a node from it. Certainly a BNode outside of the context of a graph makes very little sense.
>>> 
>> 
>> --
>> This message is automatically generated by JIRA.
>> For more information on JIRA, see: http://www.atlassian.com/software/jira
>> 
>> 
>> 

Social Web Architect
http://bblfish.net/


Mime
View raw message