Paul McNett wrote:
> Disclaimer: This response was composed over at least 90 minutes of 
> coming back to it several times in between playing with Dylan, helping 
> with dinner, and getting quite buzzed off a nice bottle of Sancerre 
> listening to The Beach Boys, Woodie Guthrie, Creedence Clearwater 
> Revival and Ramones.

Nice lineup.

> 
> 
>>>> 1. A header would be nice, like the file name.  where do you want me to 
>>>> post 
>>>> that request?
>>> Let me get this straight: you want a header with the file name, when you 
>>> ostensibly already know the file name because you are, after all, 
>>> editing it!
>> yes.  I want something there when I cut/paste it into an email, or print it, 
>> or 
>> post it to a web page.
> 
> What do you picture this header looking like?


# FrmEvents.py

or

# OPData2006/ui/FrmEvents.py

or

# app: OPData2006
# layer: ui
# file: FrmEvents.py

Maybe some time stamps, current OS user and current song being played.

> 
> 
>>> Docstrings and/or comment headers could be added if you really think 
>>> they'd add value, such as describing what it is this file does.
>> I don't think useful Docstrings can be generated.  but I am thinking:  what 
>> info 
>> is available at the time of generation that might come in handy later?  
>> database 
>> name?  list of fields and data types?  some of this stuff might be worth 
>> jamming 
>> in as comments.   Maybe the create table command in the SQL lite syntax.
> 
> It's a kind of irony, because the rest of your message is ranting at all 
> the places where we generate code, but here you are arguing for 
> generating more stuff!

We need something in the file :)  I just don't want anything that can be buggy. 
  most of my comments don't cause bugs.

> 
> As you (rightly) notice, we are generating more code than necessary. You 
>   actually haven't found the place where it is really egregious: take a 
> look at the PagSelect*.py files. Now that is *icky*

wow. I am just going to pretend I didn't see that :)


> and really should be 
> calling a common method in the superclass for adding the controls,

I'll see what I can do.  Any design plan like thoughts?  I have 2:

1. data driven (i think this is what is being done somewhere, so probably hook 
into the same data)
2. the layout needs to be somewhere the 5 and 10 of this line:

gsz = dabo.ui.dGridSizer(vgap=5, hgap=10)

Could be stored as part of #1, but I think it should be something that can be 
edited with the dabo GUI editor.  I need to dig into the dabo tools more.

>>>> 2. Why all the imports?  FrmBase seems to be the only one needed, and I am 
>>>> not 
>>> Ok, the 'import os' isn't needed. Must be a holdover from something 
>>> subsequently removed. But the other imports are needed. See 
>>> initProperties().
>> ack! missed that before.  now I have more to rant about:  put that stuff in 
>> the 
>> super class!
> 
> This part of the code shows them how to set which classes to use for the 
>   grid, the edit page, and the select page for this particular form. How 
> can that get moved to the superclass without taking away that part of 
> the show?

ok, you got me here.  sort of.  I am going to have to wiggle...

PageSelectName = 'PagSelect' + self.BizObjName
self.SelectPageClass =  getattr(  __import__(PageSelectName), PageSelectName )

(I think __import__(PageSelectName) will return the module... didn't test this 
one.  if it doesn't, I am sure there is something like this )

That is leaning on self.BizObjName more than I like.  quick thoughts: the 
AppWiz 
generated the classes with robotic consistency, so they will all be named the 
same.  so change .BizObjName to .EntityName.  Out the door it will work.  what 
I 
don't know is if it will create more hassle when you want to break the pattern. 
  my hunch is it will be the same amount of work either way, but the default 
will be cleaner.    but ignore all this for now.  I have a feeling it doesn't 
matter.


>>>> 3. self.super() - I thought the x_pre()/x()/x_post() pattern kept you from 
>>>> having to run the code in the super class because there was none?
>>> What if you put some stuff in the FrmBase method? You'd want that to 
>>> fire, no?
>> ack - I forgot the controlling method: x() calls x_pre()/x_execute()/x_post()
>>
>> _pre() and _post() are empty, _execute() is what does X what you would 
>> expect 
>> X() to do.  X is nothing more than:
>>
>> def x_pre(y): return true
>> def x_execuite(y): do useful stuff, return useful value.
>> def x_post(y): return true
>>
>> def x(y):
>> if x_pre(y):
>>      r=x_execute(y)
>>      x_post(y)
>> return r
>>
>> Now in the sub class you can put code in _pre and _post and don't have to 
>> worry 
>> about calling .super.
> 
> That isn't the point. The point is that our Dabo framework code can put 
> stuff in _pre and _after without worrying that the user subclass code 
> will forget to call super(), and thus keeping our framework code from 
> running.

I think the point of that pattern is to give the lower classes a place to put 
code.  Why would you the framework dev put code in _pre and not _execute?   but 
see my next comment.

> 
> 
>> I heard Ed talk about this pattern somewhere.  VFE has it everywhere, and it 
>> is 
>> kinda nice.  however, I have always wondered how useful it really is.  The 
>> same 
>> thing can be accomplished by having just x(). if the app developer wants 
>> more 
>> code, it goes in the subclass doing a self.super() at the appropriate place.
>>
>> I think the usefulness is readability, but I am not sure the lack of an 'if' 
>> and 
>> '.super()' make it any more readable.
>>
>> but useful or not, you should be consistent - if you are going to use the 
>> pattern, don't abuse the pattern ;)
> 
> Can you explain, in a sentence, and realizing that we aren't inside your 
> brain and frame of reference, world view, etc., how you think we are 
> abusing it? Basically, self.super() is exactly like vfp's dodefault().

I am saying you aren't using this pattern
x() calls x_pre()/x_execute()/x_post()
to solve the problem it solves.

Assuming the problem is having to remember to call .supper(), which is hardly a 
problem.  Ed, you seem to be on top of this problem/pattern... what is the 
point 
of it?   Why not just have one method and expect that .super() is used when it 
is needed?

> 
> 
>> rolling Ed's comments into here:
>>
>>>     Exactly. There is no code in the *framework* for those methods. But  
>>> you have two levels of sub-framework classes, and it sure doesn't  
>>> hurt to add that call. Technically, though, the super() call in  
>>> FrmBase.initProperties() is not needed, since initProperties() is  
>>> empty at the framework level. Again, though, it doesn't hurt, and is  
>>> more of a "belt-and-suspenders" design.
>> It does hurt:
>> 1. it makes the reader think the super class does something.
>>
>> 2. It makes tracing in a debugger harder if you are stepping though the 
>> code, 
>> and you have to step into it to see what it does. The warp to some other 
>> place 
>> and back is distracting.
> 
> We can take the self.super() out of FrmBase, but taking it out of the 
> subclasses of FrmBase wouldn't be good, because then the user would have 
> to put it in if they ever put any code in the FrmBase methods.
> 

To me "good" is only using .super() when needed.  as opposed to your good where 
you put it all over the place and make me have to hit "Step" at least one more 
time.  assuming I ever figure out how to use a debugger.  I have used pdb, and 
I 
am not going to step dabo in pdb.

I can see the good in have it there for the developer.  maybe put the lines 
there but comment them out?  That seems to address both our concerns, but sure 
seems odd.

> 
>>>> 4. self.NameBase = "frmEvents", self.Caption = "Events"...  shouldn't 
>>>> these 
>>>> things be in an xml file?
>>> If you are into that sort of thing, this is basically what the 
>>> fieldspecs option does. Check the "use fieldspecs" checkbox in the 
>>> wizard to see the difference in the generated code. Actually, that page 
>>> was removed. Edit line 753 in AppWizard.py to set useFieldSpecs to True. 
>>> Notice that your application has far fewer files, and you can edit the 
>>> field/column definitions inside ui/fieldSpecs.fsxml which will propagate 
>>> to pretty much the entire UI. There are pros/cons to each way, and I 
>>> think each is valid. Use what you like the most, but the non-fieldspecs 
>>> way will give you a much better feel for how to write actual Dabo code, 
>>> and will give you more control to make the customizations you want, and 
>>> to scale up as you go.
>> I have to disagree, as strongly as someone with 30 min of experience can. :)
> 
> I think you should try both ways, and spend more than 30 minutes with 
> it, and do more than one app, and then come back with specific changes 
> in the form of an 'svn diff' and then we can discuss it.

do any of my VFP minutes count?  :)

> 
> 
>> I think you spent too much time editing .spr files and thought that was a 
>> good 
>> thing :)
> 
> Why in the world would I ever edit an spr file? 

scroll up and find the part where you say  "more control to make the 
customizations you want" :)

don't take things ending in smilies too seriously.  in this case I was taking 
something to an extreme, which can sometimes be insightful, and is also often 
funny.

> A vcx or scx, sometimes 
> out of necessity because of VFP's inability to sort out inheritance in 
> some edge cases, prg files sure, but I don't recall ever hand-editing a 
> generated spr file.

That was my point - generated code shouldn't be edited.  but I also see how 
this 
is different, given your next comment:

> 
> What you are implying is that the AppWizard generated output is meant to 
> be regeneratable, which is false. Generate the code, tweak, maintain, 
> and never regenerate.
> 

na, I wasn't thinking of regenerating.. but now that you mention it.. maybe 
that 
would be a good way to add new fields :)

JUST KIDDING!!!  that would be a bit too out there.

> 
>> I will have to get back to you after I have spent another 30 min or so.
> 
> Please do!
> 
> 
>> Ed says:
>>>     The plan in the future is to give an option to generate code, as is  
>>> currently done, or to generate files compatible with the Class  
>>> Designer. This way you can take the generated files and either edit  
>>> them in a text editor, if that's your preference, or in the Class  
>>> Designer/IDE, if you prefer that way of working.
>> Ok, that explains why the old way was turned off.  still skeptical that the 
>> generated code is a good thing.
> 
> Healthy skepticism is a good thing. Absolutism isn't.
> 
> 
>>>> 5. afterInit(self) is just one big constant wrapped around "Events", 
>>>> right?  so 
>>>> why isn't the code in an abstract class that reads "Events" from an 
>>>> attribute ?
>>> afterInit() is a method that gets called from the dPemMixin superclass 
>>> after most of the initialization phase has been completed. I don't 
>>> understand what you mean about it being "one big constant". 
>> The constant is the 'afterInit templete' that has the name of the table 
>> stuffed 
>> into the middle of this line:
>>
>> primaryBizobj = app.biz.Events(app.dbConnection)
>>
>> So most of that line and the other 4 lines (and comments) are the same in 
>> every 
>> frmFoo.py that was generated.
> 
> We make no bones about this being generated code.
> 
> 
>> Why isn't the last line: self.creation() in the super class, right after the 
>> call to afterInit()?
>>
>> The rest of the code should be reduce a line in
>>      def initProperties(self):
>>              self.BizObjName ="Events"
>>
>> and then in the super class,
>>
>>      # Instantiate the bizobj:
>>      app = self.Application
>>      primaryBizobj = getattr( app.biz, self.BizObjName)(app.dbConnection)
>>
>>      # Register it with dForm:
>>      self.addBizobj(primaryBizobj)
> 
> You are right, of course. That would be better generated code. It would 
> be even better to remove the comments and reduce it to:
>       app = self.Application
>       self.addBizobj(getattr(app.biz, self.BizObjName)(app.dbConnection)
> 
> And then we could leave off the afterInit() in the subclass entirely, 
> and just tell people when they want to add a child bizobj to do 
> something like:
> 
>       def afterInit(self):
>               self.super()
>               app = self.Application
>               primarybiz = self.getBizobj()
>               primarybiz.addChild(getattr(app.biz, 
> "venues")(app.dbConnection))
> 
> Which would indeed be a bit better. Patches accepted. 

Before I start submitting patches I want to get a feel for what some of the 
"ideals" are, and how close they are to mine.  for the most part we are in the 
same grove.

 > You have to
> understand the evolution of the AppWizard. It was only relatively 
> recently that we even had a FrmBase defined. So the next step of better 
> abstraction, in light of also maintaining compatibility with the 
> fieldspecs way, never occurred.
> 
> I don't think it is such a big deal, but everyone has their own idea of 
> what the AppWizard is supposed to be. I happen to think it does a great 
> job doing what it is intended to do as it is. And the comments and 
> repeated code only serve to show people the calls they need to make.
> 
> 
>>> The code is 
>>> here in the FrmEvents subclass so that the developer can see what steps 
>>> need to happen in a non-abstract way, and to easily override or modify 
>>> the behavior. For example, if you want a child bizobj you just write the 
>>> python code to do that underneath the instantiation of the primaryBizobj.
>>>
>>> Again, this generated code isn't meant to be static, it is meant to be 
>>> customized. When making a new app, I'll start with the AppWizard. But 
>>> then I'll modify, tweak, add, remove and end up with something much more 
>>> than what the AppWizard did for me.
>> Use OOP the way I say!  or ponder my ranting in the hopes that it isn't a 
>> complete waste of time.
> 
> Not a waste at all. Thanks for the debate and discussion. 

You're welcome.  Thanks for responding in the same week :)

C


_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev

Reply via email to