From: Justin F. <je...@ey...> - 2001-07-08 01:50:57
|
Alex/Guys: Look, I don't mind exposing my ignorance, but I am floundering around trying to get "experience" in bolting modules together and to establish some standards for our company's coding. What I am sort of wrestling with, now, is the tradeoff between: 1. Writing code "correctly" 2. Trying not to clutter up global scope with potential danger of name clash 3. Increase performance, or the corrollary, not inadvertantly decrease performance. I will give you an example, here, which you may not think typical. I have bolted together an "application" with a module that allows you to UPDATE/INSERT/DELETE, find in any field, sort on any field, jump to any record, browse all records for all databases in my system. It works quite well, and is a general module that I can bolt into other "applications". Since it is general, it makes one humungous number of SELECT's in the constructor when you must fetch/SELECT - All database names - All tables in each database, meaning, additionally * field names * field types * field lengths * field options which I collect and put into a large data structure. This module/Class is called EditTable. OK, this is a big hit on MySQL, all done in the constructor. You can even see the page generation is slow, even on a development machine with your "private" database(s). You can imagine what it would be if you have 50 databases with 10 tables each, each table having, say 10 fields, and 50 clients using it. Now, being a good boy, in other classes, when I need this class, or something from it, I instantiatiate it with a new EditTable inside another module instead of having the EditTable module put the data structure in global scope one time, and have other modules go check on the existence of that data structure, and if not there, do a new EditTable. It is interesting to watch MySQL query logging each time EditTable gets instantiated. But, I am going to use this data structure in a Report Generator, where you need the same kind of data to be able to generate reports dynamically, and in other modules. So, I have a tension between going global, meaning, putting the data structure global, so I don't have to instantiate a new instance of EditTable, and taking the big MySQL hit over and over, technically unnecessary. THIS WAS NOT THE CASE when the modules used Init(), as, in theory Init() was only called once when loaded by BC, no matter how many times you instantiated the class inside another module. Before, you had to specifically call Init() again (if you needed to, with options/different args). Thus, the switch to constructors has caused a "penalty" when you have a whole bunch of database work in the constructor. What would you guys do? Is it even worthwhile to consider asking Alex for some kind of registration facility for things/(big things) that indeed have a good reason for being global? Yes, I do respect Alex's "law" that he wants globals to be held to a minimum. What is the sweet compromise here???? _jef -- Justin Farnsworth Eye Integrated Communications 321 South Evans - Suite 203 Greenville, NC 27858 | Tel: (252) 353-0722 |
From: alex b. <en...@tu...> - 2001-07-08 02:10:43
|
> What I am sort of wrestling with, now, is the tradeoff between: > > 1. Writing code "correctly" Which is partially subjective :) > 2. Trying not to clutter up global scope with potential > danger of name clash Definitely want to avoid that at all costs. > 3. Increase performance, or the corrollary, not inadvertantly > decrease performance. Right. But you have fairly little to worry about there, this is PHP after all. > I will give you an example, here, which you may not think > typical. > > I have bolted together an "application" with a module that allows > you to UPDATE/INSERT/DELETE, find in any field, > sort on any field, jump to any record, browse all records > for all databases in my system. It works quite well, and is a > general module that I can bolt into other "applications". Cool, the lister :) > Since it is general, it makes one humungous number of SELECT's > in the constructor when you must fetch/SELECT > > - All database names > - All tables in each database, meaning, additionally > * field names > * field types > * field lengths > * field options wow, that is big. > which I collect and put into a large data structure. This module/Class > is called EditTable. > > OK, this is a big hit on MySQL, all done in the constructor. > You can even see the page generation is slow, even on a development > machine with your "private" database(s). > You can imagine what it would be if you have 50 databases with > 10 tables each, each table having, say 10 fields, and 50 clients > using it. Right, because you are doing a _huge_ amount of "discovery" for every action, which seems unnecessary. > Now, being a good boy, in other classes, when I need this class, or > something from it, I instantiatiate it with a new EditTable inside > another module instead of having the EditTable module put the > data structure in global scope one time, and have other modules go check > on > the existence of that data structure, and if not there, do That will screw you re: performance. You should be using it by reference (=&) to avoid creating a copy of the object. That's memory intensive as hell :) > a new EditTable. It is interesting to watch MySQL query logging > each time EditTable gets instantiated. You should make your "discovery" data available in a var of the class so other modules can ask it questions. > But, I am going to use this data structure in a Report Generator, > where you need the same kind of data to be able to generate reports > dynamically, and in other modules. I'm thinking we probably need to (unfortunately) allow for unique names in module declaration arrays, so modules can refer to each other simply. > So, I have a tension between going global, meaning, putting the > data structure global, so I don't have to instantiate a new > instance of EditTable, and taking the big MySQL hit over and > over, technically unnecessary. > > THIS WAS NOT THE CASE when the modules used Init(), as, in theory > Init() was only called once when loaded by BC, no matter how many times > you instantiated > the class inside another module. Before, you had to specifically > call Init() again (if you needed to, with options/different args). Right, but it isn't specifically a result of not using Init anymore. You should be putting that stuff in a var in your module, which other modules can "see". > Is it even worthwhile to consider asking Alex for some kind of > registration > facility for things/(big things) that indeed have a good reason for > being global? I have considered that, and I still can't quite justify it. You can do all of that talking-between-modules stuff with a combination of load order and well designed class variable structures in the modules. > Yes, I do respect Alex's "law" that he wants globals to be held to > a minimum. What is the sweet compromise here???? Try and put your data in a class var in the module that gets the stuff from mysql, then have your other module(s) get that class var. The reason I mentioned the naming thing above is because we instantiate modules inside Page->modules[position_in_load_order] - so you'd be using the load order which is page specific (i.e. that won't work well at all) I can see potentially wanting to add the "unique name" concept to $bc_page['modules']['group'][x] because you might want to have the ability to address modules individually (even if there are multiple instances of a module on a page. That last thing needs quite a bit of thoght, because it can cause problems: -unnecessary amount of work if you don't need to address modules individually -could potentially be easier to just assume that the import path is the unique name and reference the module that way (though this has other problems) -egh, need to think about that one. --------- in any case, this _is_ quite useful justin: this real world example is perfect. it _is_ easier to just create a module comm manager or something that gets loaded up only if a module needs to communicate, and have another module grab the variable from that module communications manager. I'll think about that one and get back to you. _a |
From: Justin F. <je...@ey...> - 2001-07-08 03:00:24
|
alex black wrote: [== snip, snip ==] > > Yes, I do respect Alex's "law" that he wants globals to be held to > > a minimum. What is the sweet compromise here???? > > Try and put your data in a class var in the module that gets the stuff from > mysql, then have your other module(s) get that class var. > > The reason I mentioned the naming thing above is because we instantiate > modules inside Page->modules[position_in_load_order] - so you'd be using the > load order which is page specific (i.e. that won't work well at all) > > I can see potentially wanting to add the "unique name" concept to > $bc_page['modules']['group'][x] because you might want to have the ability > to address modules individually (even if there are multiple instances of a > module on a page. > > That last thing needs quite a bit of thoght, because it can cause problems: > -unnecessary amount of work if you don't need to address modules > individually > -could potentially be easier to just assume that the import path is the > unique name and reference the module that way (though this has other > problems) > -egh, need to think about that one. [=======================] This is true, it is something else that I have "wondered" about, namely I already "use" multiple loads of the same module, even if it is a place holder called Blank.php. I wondered if name mapping was possible, but I am always asking... I really find programming with BC a, er, what, paradigm change in thinking. The nice problem with BC is, you are smothered with a plethora of riches, you can do things in several different ways, but you wish to retain generality, and all that good stuff. It is taking me some time to "feel" how to adjust things like module granularity, module functionality. Like do you create "thin" lookup tables, do you break out that huge data structure previously referred to as a module in itself, ad infinitum. But, it is fun. BC is a cafeteria with 52 kinds of cheesecake... I hope we discover as early as possible what we really "need". This does not imply that BC is bloated, on the contrary. Again, good job, Alex. _jef -- Justin Farnsworth Eye Integrated Communications 321 South Evans - Suite 203 Greenville, NC 27858 | Tel: (252) 353-0722 |