I've been watching Elixir from afar for some time while using SQLAlchemy. When using SQLAlchemy I've been using the mapping functions inside of SQLAlchemy directly, and like many I've found that to be somewhat repetitive and less than intuitive. I had Elixir recommended to me by a few people, but the syntax has turned me off to it. I'm aware that the DSL nature of it will allow you to create your own statements, and I do realize this is a powerful feature, but it's not what I was looking for in an ORM wrapper.
I was looking for was a syntax that allowed me to write natural Python classes - not unlike what Django's syntax is now, or what TurboEntity used to have. A rails-style DSL has it's advantages, but I doubt I'm alone in feeling that, if nothing else it /looks/ awkward. Simply put, when I want to say that a object will have an integer field, I'd expect to write:
class MyObj(ParentClass): number = Integer
This is close to both the SQLAlchemy and Python ways of doing things. On the other hand, I just find that:
class MyObj(ParentClass): has_field('number', Integer)
doesn't convey what I was trying to code: I wanted an Object with a .number attribute that is an Integer. Putting it into a string means that the backend code has to do some setattr(obj, 'number',...) magic, and advantages of being able to define your own statements notwithstanding, being able to write idiomatic Python code was what I was looking for in a declarative layer.
So, mostly I'm just wondering if the devs would be amenable to a "traditional" syntax for Elixir, and if users would be interested in seeing it, or if the DSL syntax is OK for most programmers. I know that Ben Bangert brought up this issue back in May and the decision was to "steer clear of the discussion" for the time being, but now seems like as good a time as any to bring it back up :). I'm not averse to starting a separate project for an OOP-style declarative layer, but I do want to touch base here to make sure that it isn't something that's planned as an Elixir feature.
> I've been watching Elixir from afar for some time while using > SQLAlchemy. When using SQLAlchemy I've been using the mapping > functions inside of SQLAlchemy directly, and like many I've found that > to be somewhat repetitive and less than intuitive. I had Elixir > recommended to me by a few people, but the syntax has turned me off to > it. I'm aware that the DSL nature of it will allow you to create your > own statements, and I do realize this is a powerful feature, but it's > not what I was looking for in an ORM wrapper.
> I was looking for was a syntax that allowed me to write natural Python > classes - not unlike what Django's syntax is now, or what TurboEntity > used to have. A rails-style DSL has it's advantages, but I doubt I'm > alone in feeling that, if nothing else it /looks/ awkward. Simply put, > when I want to say that a object will have an integer field, I'd > expect to write:
> class MyObj(ParentClass): > number = Integer
> This is close to both the SQLAlchemy
How is this close to SQLAlchemy?
> and Python ways of doing > things. On the other hand, I just find that:
> class MyObj(ParentClass): > has_field('number', Integer)
> doesn't convey what I was trying to code: I wanted an Object with a > .number attribute that is an Integer. Putting it into a string means > that the backend code has to do some setattr(obj, 'number',...) magic, > and advantages of being able to define your own statements > notwithstanding, being able to write idiomatic Python code was what I > was looking for in a declarative layer.
The setattr thing will be there whether you notice it or not.
> So, mostly I'm just wondering if the devs would be amenable to a > "traditional" syntax for Elixir, and if users would be interested in > seeing it, or if the DSL syntax is OK for most programmers. I know > that Ben Bangert brought up this issue back in May and the decision > was to "steer clear of the discussion" for the time being, but now > seems like as good a time as any to bring it back up :). I'm not > averse to starting a separate project for an OOP-style declarative > layer, but I do want to touch base here to make sure that it isn't > something that's planned as an Elixir feature.
Ok, here is my take on it. For simple fields, I prefer the OO syntax too. For relationships, I slightly prefer the DSL style.
In an hypothetical world where there wasn't anybody using the DSL syntax, I'd personally be ok to go back to an OO style syntax. Now, we are in the real world, so the DSL syntax is going to stay.
Now, do we want to support both syntax? It wouldn't be hard to do I think. The problem is with the documentation and how we present things. That might bring some confusion to have yet another syntax.
On the other hand, I'd find it really a shame if somebody (you or anybody else) started another declarative layer just because of the syntax, while most (95% at least) of the codebase could be common. So honestly, I don't know what to do. I'd be okay to (at least try to) make the code work both ways, and leave the OO way mostly undocumented (it would only be an alternative to the "official" syntax) but Jonathan might not agree with me on this since he likes the DSL thing a lot (it was his idea after all).
Gaetan de Menten wrote: > Now, do we want to support both syntax? It wouldn't be hard to do > I think. The problem is with the documentation and how we present > things. That might bring some confusion to have yet another syntax.
> On the other hand, I'd find it really a shame if somebody (you or > anybody else) started another declarative layer just because of the > syntax, while most (95% at least) of the codebase could be common. So > honestly, I don't know what to do. I'd be okay to (at least try to) > make the code work both ways, and leave the OO way mostly undocumented > (it would only be an alternative to the "official" syntax) but > Jonathan might not agree with me on this since he likes the DSL thing > a lot (it was his idea after all).
Okay, I have had lots of discussions on this over the past few months, and its becoming more and more clear that the majority of people prefer the more traditional approach when it comes to defining fields. So, with that said, I think we need to listen to our users here, and start supporting the traditional syntax, but only for defining fields. I think the relation style needs to remain as a DSL-like approach.
That being said, I think its time that we went ahead and deprecated `with_fields` in favor of the "OO" approach, since the syntaxes will end up being quite similar, with the added bonus of preserving field order:
class Person(Entity): id = Field(Integer, primary_key=True) name = Field(String)
has_many('pets', of_kind='Pet', inverse='owner')
In the long-term, we might want to deprecate `has_field` as well, so that we will have only one way to do things. I am hesitant to do this right now, but I haven't been happy having two ways to do the same thing for some time now, and I think we need to resolve this at some point.
So, the long and short of it is that I will finally break down, so I don't have to hear about it anymore ;) So, whoever wants this, please go ahead and work on a patch, and we'll try to get it into the 0.4 release so that people can use it sooner rather than later. I want this to be the last major API breakage before we release 0.4, and hopefully for a long time to come. The patch should contain tests and documentation updates before we'll accept it.
On Aug 29, 8:21 am, AdamG <akgo...@gmail.com> wrote:
> So, mostly I'm just wondering if the devs would be amenable to a > "traditional" syntax for Elixir, and if users would be interested in > seeing it, or if the DSL syntax is OK for most programmers. I know > that Ben Bangert brought up this issue back in May and the decision > was to "steer clear of the discussion" for the time being, but now > seems like as good a time as any to bring it back up :). I'm not > averse to starting a separate project for an OOP-style declarative > layer, but I do want to touch base here to make sure that it isn't > something that's planned as an Elixir feature.
I am new to world of databases in general and using Elixir has solved many of my needs and made it enjoyable at the same time. But recently I've been interested in trying to do things in less orthodox ways and I think I hit a wall [1] with Elixir. I don't know if that wall can be overcome easily or not, but I think I hit that wall in the first place because I was expecting Elixir objects behave like regular objects and thus I wanted to try some more advanced features that Python language offers.
I think it would be great if Elixir objects behaved more like Python objects. Hopefully this would make those objects more easily manipulable and combined with other types of Python idioms and tools that are the reason why I love using Python so much in the first place.
I hope I understood the issue ... If not, pardon my ignorance ... :-)
--- [1] In case anybody is wondering, my main issue is how fields are declared. I've been reviewing the process and all that getframe hacking is a neat thing that I had never ever thought of or had to deal directly before, but certainly it is not how I expected things to work.
> Okay, I have had lots of discussions on this over the past few months, > and its becoming more and more clear that the majority of people prefer > the more traditional approach when it comes to defining fields. So, > with that said, I think we need to listen to our users here, and start > supporting the traditional syntax, but only for defining fields. I > think the relation style needs to remain as a DSL-like approach.
> That being said, I think its time that we went ahead and deprecated > `with_fields` in favor of the "OO" approach, since the syntaxes will end > up being quite similar, with the added bonus of preserving field order:
> class Person(Entity): > id = Field(Integer, primary_key=True) > name = Field(String)
> In the long-term, we might want to deprecate `has_field` as well, so > that we will have only one way to do things. I am hesitant to do this > right now, but I haven't been happy having two ways to do the same thing > for some time now, and I think we need to resolve this at some point.
> So, the long and short of it is that I will finally break down, so I > don't have to hear about it anymore ;) So, whoever wants this, please go > ahead and work on a patch, and we'll try to get it into the 0.4 release > so that people can use it sooner rather than later. I want this to be > the last major API breakage before we release 0.4, and hopefully for a > long time to come. The patch should contain tests and documentation > updates before we'll accept it.
Sounds good! I've got a test set up with that syntax, and am trying to add in the support by adding a function to handle the dict_ parameter on the init function of EntityMeta - would that be the right place to do this? I'm mostly using the source of Statement.process and one of the earlier TurboEntity releases as references, so if there's a better place for it to be, let me know. It's not working as of yet, but the long weekend coming up should be a good time to get it finished & submitted. Should the patches be submitted to Trac now, or directly to the devs, or ...?
Writing the patches ended up being pretty straightforward. Included are the following:
* A patch to elixir/entity.py (assignment_syntax.patch) that adds a process_attrs() method to EntityMeta, and calls it in __init__().
* A patch to docs/tutorial.rst (tutorial_assignment_syntax.patch) which updates the code samples to use class assignment rather than with_fields.
* The test_attr_syntax.py file, which is mostly a copy of test_movies.py, just with the class attribute syntax.
All the patches are against SVN revision 193.
All tests still run successfully with SQLAlchemy 0.4. I did have to make an unrelated fix on elixir/ext/associable.py to get it to work with 0.4, but that was the case before or after these patches. I don't have access to a machine with 0.3 right now, but I will tomorrow.
> ---------- Forwarded message ---------- > From: AdamG <akgo...@gmail.com> > Date: Aug 30, 8:54 am > Subject: DSL vs. OOP Syntax > To: SQLElixir
> On Aug 29, 10:36 am, Jonathan LaCour <jonathan-li...@cleverdevil.org> > wrote:
> > Okay, I have had lots of discussions on this over the past few > > months, and its becoming more and more clear that the majority of > > people prefer the more traditional approach when it comes to > > defining fields. So, with that said, I think we need to listen to > > our users here, and start supporting the traditional syntax, but > > only for defining fields. I think the relation style needs to > > remain as a DSL-like approach.
> > That being said, I think its time that we went ahead and deprecated > > `with_fields` in favor of the "OO" approach, since the syntaxes > > will end up being quite similar, with the added bonus of preserving > > field order:
> > class Person(Entity): > > id = Field(Integer, primary_key=True) > > name = Field(String)
> > In the long-term, we might want to deprecate `has_field` as well, so > > that we will have only one way to do things. I am hesitant to do > > this right now, but I haven't been happy having two ways to do the > > same thing for some time now, and I think we need to resolve this > > at some point.
> > So, the long and short of it is that I will finally break down, so I > > don't have to hear about it anymore ;) So, whoever wants this, > > please go ahead and work on a patch, and we'll try to get it into > > the 0.4 release so that people can use it sooner rather than > > later. I want this to be the last major API breakage before we > > release 0.4, and hopefully for a long time to come. The patch > > should contain tests and documentation updates before we'll accept > > it.
> Sounds good! I've got a test set up with that syntax, and am trying to > add in the support by adding a function to handle the dict_ parameter > on the init function of EntityMeta - would that be the right place to > do this? I'm mostly using the source of Statement.process and one of > the earlier TurboEntity releases as references, so if there's a better > place for it to be, let me know. It's not working as of yet, but the > long weekend coming up should be a good time to get it finished & > submitted. Should the patches be submitted to Trac now, or directly to > the devs, or ...?
As a supporter and heavy user of the `with_fields`-syntax I like your proposal. It seems easier to use and looks more natural to me. And it would remove lines of code (and a level of indentation) in most of my cases.
On 29 Aug., 16:36, Jonathan LaCour <jonathan-li...@cleverdevil.org> wrote:
> That being said, I think its time that we went ahead and deprecated > `with_fields` in favor of the "OO" approach, since the syntaxes will end > up being quite similar, with the added bonus of preserving field order:
> class Person(Entity): > id = Field(Integer, primary_key=True) > name = Field(String)
> In the long-term, we might want to deprecate `has_field` as well, so > that we will have only one way to do things. I am hesitant to do this > right now, but I haven't been happy having two ways to do the same thing > for some time now, and I think we need to resolve this at some point.
> [...]
> Gaetan, Daniel, how do you guys feel about this?
> Writing the patches ended up being pretty straightforward. Included are > the following:
> * A patch to elixir/entity.py (assignment_syntax.patch) that adds a > process_attrs() method to EntityMeta, and calls it in __init__().
> * A patch to docs/tutorial.rst (tutorial_assignment_syntax.patch) which > updates the code samples to use class assignment rather than > with_fields.
> * The test_attr_syntax.py file, which is mostly a copy of > test_movies.py, just with the class attribute syntax.
> All the patches are against SVN revision 193.
> All tests still run successfully with SQLAlchemy 0.4. I did have to > make an unrelated fix on elixir/ext/associable.py to get it to work > with 0.4, but that was the case before or after these patches. I don't > have access to a machine with 0.3 right now, but I will tomorrow.
Care to explain what was that fix? (or maybe we already corrected that in the mean time).
> Let me know how this is.
These patches look good to me. For consistency's sake, I'd appreciate if you'd implement the same for relationships. This shouldn't be difficult though. It'll only be a tiny bit more work than for fields, as you'd have to make Relationships be initializable without knowing their name (as was already the case for fields).