RJLRef: $PH/COOL-BDE/bdeRefactoringTasks060821.txt (linked from $PH/06f522/non-browsable-links/bdeRefactoringTasks060821.txt) Subj: Ideas for 06f522 refactoring bde/{src,pr_util} FYInfo Here are more thoughts on bde refactoring of both high-level methods with switch cases, and low-level field get/set functions. Both levels I suggest splitting into sequential steps that are testable. R Lechner > From ralmonte@cs.uml.edu Mon Aug 21 18:39:13 2006 > From: Robert Almonte > To: Bob Lechner > CC: sfrye@cs.uml.edu > Subject: Re: G3/2005 ideas on refactoring pr_util FYInfo > > Hi Prof. Lechner, > Yes, you are right. > I think that I got deviated from that since at the time, the semester > class was focusing in that. > We didn't want to overlap. > > Which kind of refactoring is this C or C++? [RJL: (assuming I know what 'this' means: :-): chgen generates pr_util_*/*.{c,h}. and gencpp generates pr_util/*.{cc,h} Where bdegen13 table XX is a List of XX_row struct instances, and bdegencpp table XX is a List or Vector container class that holds XX_row class object instances. gencpp produces XX_schema.h as well as bde's global schema.h. Refactoring involves slight but unavoidable mods to child_loop navigation. ntansala describes how in $PH/COOL-GEN/gencpp/gencpp_help_nt.txt: In particular, gencpp's table XX_specific {set,get}_fieldname methods replace chgen's pr_{set,get}_type functions. Chgen13 later added the outpt file pr_accessor with XX_{get,set}_fieldname methods. (TBD: convert bde to use pr_accessor.c methods as an intermediate step in refactoring bde/src code (or other GEN app) for gencp. This permits retesting bde with pr_util.a from chgen before recompiling bde to use pr_util.a from gencpp. The remaining step is simply to remove the XX_ prefix from pr_accessor methods since these are already prefixed by a class-specific pointer like HNcurr->get_HNid(); CHGEN13 Example: ------------------ $RBGB/pr_util_nolog/pr_accessors.c (from chgen13) gives an example of a function to load an EI-row instance field Int1 from value: The SETROUTINE macro generates this function: -------- ** SETROUTINE(void, EI, EventInstance,EI,Int1,int) produces ** ** FUNCTION2( ** void EISetInt1(, ** hcg_key, EIid1, ** int, value ** ) ** { ** pr_find(EI, EIid, EIid1);// search: alters EIcurr ** if (EIcurr != NULL) ** EIcurr->Int1 = (int)value; ** } ---------- which after expanding the macro FUNCTION2 defines the EI-method void EISetInt1(hcg_key EIkey, int value) { pr_find(EI, EIid, EIkey); // alfers private EIcurr if (EIcurr != NULL) EIcurr->Int1 = (int)value; } (pr_find's search is the price of not requiring the pre-condition of the form (EIcurr->EIid == EIkey.) THis function can be called as EISetInt1(EIid1, Int1value); GENCPP Example: ------------------ Gencpp has a table-specific method which avoids the EventInstance name or its abbreviation EI. For table type EI and field Int1, gencpp would define an EI-class method set_Int1(int value). I.e., pr_util from gencpp would support a call of the form EIcurr->setInt1(pkvalue) so chgen13's pr_accessors.c function call EISetInt1(EIid1, Int1value) would have to be replaced by the call to gencpp's equivalent: set_Int1(Int1value); and requires the pre-condition (EIcurr->EIid == EIid1). The output of GENCPP is shown for the student DB test case in $PH/COOL-GEN/gencpp/gencpp_ntansalarak/test/CHGEN_GENCPP/GENCPP (linked to $CASE/bdelog2ks/ntansala/gencpp/test/CHGEN_GENCPP/GENCPP). Access methods for typical table ST are declared in STschema.h. For example, the fname field of table ST has two methods: (1) char* get_fname (); and (2) void set_fname (char *value); To update this field to "bob", we must call [this->]set_fname ("bob") or STcurr->set_fname ("bob"). instead of STsetfname(STid, "bob"), which would be its chgen13 equivalent method call after refactoring to use bde/pr_util_nolog/pr_accessors.c . [Note: Bde must first be refactored to this, from the current call to pr_set_ which for this ST example would be pr_set_str(STcurr, fname, "bob"); with the pre-condition: STcurr is a valid struct ST * ptr value.] Prposed 2-step Refactring Process: --------------------------------- The 2-step refactoring for this example (and for bde/src) would be: Step 1: While pr_util still comes from chgen13, convert (refactor) pr_set_str(STcurr, fname, "bob"); into STsetfname(STid, "bob") // require valid STcurr Step 2: Regenerate pr_util from gencpp, and convert (refactor) STsetfname(STid, "bob") into STcurr->set_fname("bob"). It would be prudent to modify chgen13's current output to pr_accessors.c to rename XXsetfield as XXSet_field, for conformance with gencpp, before step 1 refactoring above, for each table and field. Since this is a class-specific over-ride method in gencpp, the pre-condition assert(STcurr->STid == STkey) is satisfied on entry. Where is gencpp now? -------------------- gencpp was constrained to retain compatibility so it doesn't yet specialize most public pr_*.c methods to table types: i.e., switch statememts remain to be refactored in e.g. load_data, pr_dump). (Private methods like pr_parse already call XX::parse_row.) This is shown by the relative size of the class-specific XX_schema.h subclass generated by gencpp for each table type and the global bdeschema.h also #included. The latter would shrink as public methods migrate into XX_schema.h for each XX. This may permit refactoring of bde to call a generic method in an ancestor class and let the C++ compiler over-ride it. (However, I don't know if this matters since bde methods are already specialized to state-models and therefore table-types (but see Step 3: LCP AC and AI classs introduction below). For the current status of chgen and gencpp, see the structure charts by ntansala. She compares pr_util functions from chgen (slides 16-23) and from gencpp (slides 24-33) at $PH/COOL-GEN/gencpp/gensrcStructureCharts_nt.ppt Refactoring chgen to produce a pr_util from chgen that resembles a future one from gencpp: bde calls to most public pr_util methods from chgen are yet to be refactored to call pr_util from gencpp: Step 1: Refactored pr_util methods would hide the particular case code blocks within switch(tbl_idx) and the switch case block would become a one-line method call. Step 2: The functions that contain these switche cases are replaced by generic methods that call row_class-specific component methods inside child_loops during a walk-thru the composition tree of a diagram (step 2). Step 3: If and when Active Class AC and Instance AI are introduced as superclasses in bde (for LCP), these methods may be called inside ST components of State Models; the AC,AI pair then can declare static and instance methods respectively, as virtual functions and g++ will handle method over-rides in bde-specific subclasses. One type of bde refactoring is bde/src/conversion from pr_util*.a from chgen to pr_util*.a from gencpp. Instead of calling extern "C" functions frm chgen, bde/src becomes a client of extern *.cc functions from gencpp. A prelude to this is incremental refactoring of pr_util in C and src in c++ (in sync so the bde2pr_util interface continues to work). Some steps here are listed in $PH/COOL-BDE/bdeRefactoringTasks060820.txt Also relevant to refactoring is $CASE/2kf522/ghostvars.ppt. [end RJL] > > FYI > I updated my Linux O.S to Fedora Core 5 and I am having problem to > compile the Fox Library. > > > Bob Lechner wrote: > > RJLRef: $PH/COOL-GEN/pr_utilRefactoring > > Hi Scot. > > > > I don't believe R Almonte ever started this study of > > pr_util simplification by eliminating pr_init. > > > > A related task is to ignore version numbering in pfkeys. > > I.e., widen the row number part of the hcg_key type. > > > > The key manipulation routines are all parameter-driven: > > E.g. > > grep '_SIZE|_LEN' $RBGB/pr_util_nolog/*.{c,h} > > > > Bob Lechner > > > > > > Forwarded message: