I don't have issue with the serialization, as you said, that's only an
implementation detail. What I want to know, is why the question is about
saving/restoring *CFC's* and not *DATA*? If I deploy OpenBD on AWS, there is
no cfc persistence or built-in ORM, there is only straight
*data*persistence. If I deploy OpenBD to my home server, again there
is only
*data* persistence. Why the paradigm shift just for GAE? The problems that
are being solved are the same for any OpenBD flavor, so why not implement it
across the board in that case?
The GAE datastore is very similar to a relational db, the only significant
difference being that it has the concept of multiple values for a property
and therefore additional/different sql functions. But that characteristic
does not necessarily suggest that we need to bring cfc's into the mix.
This following code is the heart and essence of CF:
<cfquery dbtype="google" name="Visitors">
SELECT FROM Visitor
</cfquery>
<cfoutput query="Visitors">
#Visitor.IP#
</cfoutput>
Why dismiss it so quickly? Lots of people don't care to have everything in
an object. And if they do, well they can just do what they always do:
VisitorObject = new('Visitor');
VisitorObject.setIP(VisitorQuery.IP);
And to save that visitor they would just do:
GoogleWrite('Visitor', VisitorStruct);
Or:
GoogleWrite('Visitor, { IP=localhost, Name=Baz });
Or perhaps a special UPDATE statement that openbd translates to googlewrite:
<cfquery dbtype="google" name="Visitors">
UPDATE Visitor
SET IP='localhost'
</cfquery>
If they they wanted an entirely object-oriented app without worrying about
CRUD, they could just harass Mark Mandel to write a GAE Transfer that I'm
sure would be very neat and fabulous :)
The question is why force someone down that route, and change the paradigm
so significantly, when they can choose to do it themselves if they wanted
to? What am I missing here?
I see your update to the thread now:
"Only persist those variables that you (the CFML developer) specifically
> declare to be persistable, via CFPROPERTY or some other annotation
> mechanism. Searching can be done on any persistable variable that is a
> simple type (string, number, boolean, date). When you read a CFC from the
> datastore, create a new CFC instance and populate it with the persisted
> variables."
>
This is getting even closer to what I am saying. If the data is coming back
in raw form, why don't you just give it back to me like that instead of
adding additional processing to "create a new CFC instance and populate it
with the persisted variables"? What if I don't want a cfc and the extra
overhead of creating it.
Baz
Baz
On Fri, Jun 5, 2009 at 11:20 AM, Vince Bonfanti <[email protected]> wrote:
> I think you're getting too hung up on "serialization" as an implementation
> detail of the CFC persistence layer. The real questions are: What does it
> mean to save/restore a CFC to/from a persistent datastore? and, How does the
> CFML developer deal with the CFC persistence layer?
>
> For Java objects, persistence means to just save the data members, not the
> "behavior" members (methods). This might make sense for a static language;
> and, consider the complex annotation "language" (JDO) that's been developed
> to manage persistence. Go take a look at the GAE group and you'll see most
> of the questions revolve around use JDO.
>
> CFML isn't Java, CFCs aren't Java objects, and CFML developers aren't Java
> programmers. CFML is a dynamic language: you can add/remove behaviors
> (functions) from CFCs at will, you can change the types of variables, you
> can have one CFC instance that has some variables defined and another CFC
> instance of the same type that doesn't. None of this is true for Java, which
> is a static language. So the model for dealing with CFC persistence can't be
> the same as the model for dealing with Java object persistence.
>
> Forget about serialization as an implementation detail, and step back to a
> higher level: as a CFML programmer, how do you want CFC persistence to work?
> Here are my (initial) answers to this question:
>
> 1) I want it to be simple. I want to write a "plain old" CFC (without any
> persistence annotations) to the datastore and then read it back out again,
> and get back the exact same CFC that I wrote out.
>
> 2) I want to be able to query the datastore based on any variable I place
> in the CFC "this" or "variables" scope, again, without having to do any
> persistence annotations.
>
> 3) I want it to be fast so that I don't have to worry (too much) about
> performance.
>
> The current implementation reflects the above.
>
> So now we have the issue of CFC versioning (an important issue). Again,
> without referring to any implementation details, as a CFML programmer, how
> do you want this to work? If we can answer that question, then we can worry
> about the implementation details.
>
> Vince
> On Fri, Jun 5, 2009 at 1:26 PM, Baz <[email protected]> wrote:
>
>> I don't know what the *right* way is, but allow me to play devil's
>> advocate for a moment.
>>
>> Consider "method injection" techniques that are used in some frameworks,
>>> where a method is dynamically added to a CFC after it's created--don't you
>>> want that method to still be there after reading from the datastore
>>
>>
>> I'm a big fan of mixins (when used appropriately) and use them in my own
>> code, so I definitely see the coolness of this.
>>
>> There would be considerably more overhead in "deconstructing" a CFC
>>> instance and writing the constituent parts to the datastore, and then
>>> rebuilding a new CFC instance "from scratch" when reading from the
>>> datastore, compared to simply serializing and deserializing the CFC
>>> instance.
>>>
>>
>> Isn't this the same problem that any datastore has whether it is GAE or
>> relational or a text file? As cfml coders we always have the option of
>> serializing cfcs, and we can then choose to store them in a db or perhaps a
>> caching layer if we wanted to. Why change the paradigm completely in GAE and
>> force serialization on the data layer thereby complicating/limiting other
>> options? It really seems like that should be the job of a framework or a
>> caching layer. Plus won't this make it much more difficult for people to
>> port their apps, especially if the apps are data-centric rather than
>> object-based?
>>
>> On my current GAE test site (http://www.thinkloop.com) each artifact on
>> the page represents a user that is saved in the datastore (if you mouse-over
>> an artifact you will see the ip address and some other info about each
>> user). To fill the page, I need a 1000 records, and therefore a 1000 full
>> blown objects. Even with serailization it is still relatively heavy and
>> slightly slower than the equivalent site using a straight recordset.
>>
>> the CFC persistence layer isn't built on top of JDO, but is written
>>> directly on top of the GAE datastore "low-level API."
>>>
>>
>> You know a lot more about this than I do, but doesn't the low-level api
>> get closer to treating the datastore like a flat text file and less like
>> objects? It would seem that this would make it more natural to treat the
>> recordset like a query than an array of objects. I really don't know much
>> about this, just asking.
>>
>> Serialization also simplifies the code within the BD persistence layer
>>> (simpler code means fewer bugs)
>>>
>>
>> I don't want to sound like a bastard but you and the team are very skilled
>> programmers and I don't think ease of implementation should be heavily
>> weighted if it comes at the cost of a better end-user experience -
>> especially at this stage of the game. Perhaps by investigating other
>> possibilities we might find that an equally clean/easy implementation exists
>> with a better end-user experience. Again, I want to re-emphasize that I am
>> being devil's advocate, and I appreciate all that you do, and that I would
>> not be able to do better myself! :)
>>
>> googleRead( oldKey, newCFC );
>>
>>
>> Having said all that, your work-around is quite clean, especially if you
>> write it in the other notation making it completely invisible:
>> newCFC.googleRead('key');
>>
>> What is it about this datastore that makes it more suitable for built-in
>> serialization than other db's?
>>
>> Baz
>>
>>
>>
>> On Fri, Jun 5, 2009 at 9:30 AM, Vince Bonfanti <[email protected]>wrote:
>>
>>> Serialization guarantees we always restore the CFC to the exact state it
>>> was in prior to being written to the datastore. Consider "method injection"
>>> techniques that are used in some frameworks, where a method is dynamically
>>> added to a CFC after it's created--don't you want that method to still be
>>> there after reading from the datastore?
>>>
>>> Serialization also simplifies the code within the BD persistence layer
>>> (simpler code means fewer bugs). There are also performance considerations,
>>> which you raised previously. There would be considerably more overhead in
>>> "deconstructing" a CFC instance and writing the constituent parts to the
>>> datastore, and then rebuilding a new CFC instance "from scratch" when
>>> reading from the datastore, compared to simply serializing and deserializing
>>> the CFC instance.
>>>
>>> BTW, you said something in a previous message about "proxying to the Java
>>> layer." This isn't what BD does at all; the CFC persistence layer isn't
>>> built on top of JDO, but is written directly on top of the GAE datastore
>>> "low-level API." Building a CFC persistence layer on top of JDO would be a
>>> big mistake in terms of complexity and performance.
>>>
>>> Having said all that, it might be useful for BD to build in some sort of
>>> versioning support to help automate this. For example, maybe we could do
>>> something like this (adding a second parameter to the GoogleRead function):
>>>
>>> <cfscript>
>>> newCFC = createObject( "component", "MyCFC" );
>>> googleRead( oldKey, newCFC );
>>> </cfscript>
>>>
>>> The above code would retrieve the old CFC represented by "oldKey" from
>>> the datastore and use it to populate the "newCFC" instance by copying all
>>> variables (except for functions) from the "this" and "variables" scopes from
>>> "oldCFC" to "newCFC".
>>>
>>> It's exactly this kind of feedback that we need to make sure the product
>>> is useful. Thanks.
>>>
>>> Vince
>>> On Fri, Jun 5, 2009 at 12:01 PM, Baz <[email protected]> wrote:
>>>
>>>> Why are we serializing cfc's again? Why not stick to the common workflow
>>>> of returning data from the datastore, then using that to initialize a new
>>>> cfc and then using memcached or some other caching layer if serialization
>>>> is
>>>> needed? The synchronization logic is non-trivial and will ALWAYS arise as
>>>> people adjust their cfc's all the time.
>>>>
>>>> Baz
>>>>
>>>>
>>>>
>>>> On Fri, Jun 5, 2009 at 6:44 AM, Vince Bonfanti <[email protected]>wrote:
>>>>
>>>>> Yes, I've run into this problem myself while working on my BlogCFC
>>>>> port. BD essentially treats CFC functions as data within the CFC "this"
>>>>> and
>>>>> "variables" scope, which means they get serialized with the CFC when
>>>>> writing
>>>>> to the GAE datastore. If you modify your CFC change the implementation of
>>>>> a
>>>>> function or add new functions, those changes don't affect CFCs that are
>>>>> already in the datastore. You'll have to deal with this manually. Two
>>>>> suggestions to make this easier:
>>>>>
>>>>> 1) Store a "version number" within your CFC "this" or "variables"
>>>>> scope and increment it whenever you modify the CFC.
>>>>>
>>>>> 2) Create an init() function for your CFC that takes another CFC as
>>>>> the argument; initialize the CFC by looping through the "this" and
>>>>> "variables" scopes and copy all the relevant variables. You can use this
>>>>> init() function to upgrade a CFC.
>>>>>
>>>>> Something like this:
>>>>>
>>>>> <cfscript>
>>>>> oldCFC = googleRead( oldKey );
>>>>> if ( oldCFC.version = "1.0" ) { // need to upgrade to version 2.0
>>>>> newCFC = createObject( "component", "MyCFC" );
>>>>> newCFC.init( oldCFC );
>>>>> googleWrite( newCFC );
>>>>> googleDelete( oldCFC );
>>>>> }
>>>>> </cfscript>
>>>>>
>>>>> Vince
>>>>> On Fri, Jun 5, 2009 at 2:15 AM, Baz <[email protected]> wrote:
>>>>>
>>>>>> If someone were persisting their cfc's to the datastore, then needed
>>>>>> to update the code, a problem arises. The cfc's that were stored in the
>>>>>> past
>>>>>> will be de-serialized to old components that are missing new methods and
>>>>>> code updates that may be needed by the updated app. Does the application
>>>>>> have to manage the synchronization of cfc's in the datastore?
>>>>>>
>>>>>> Baz
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
> >
>
--~--~---------~--~----~------------~-------~--~----~
Open BlueDragon Public Mailing List
http://groups.google.com/group/openbd?hl=en
official site @ http://www.openbluedragon.org/
!! save a network - trim replies before posting !!
-~----------~----~----~----~------~----~------~--~---