The code is separated in a way that creates as few redirects as possible. The large pieces that you see are split into much smaller units. The smaller units are the ones that I need to track. The large piece, I can track through the http requests.
The purpose of these large segments are to force BaseX to update when upcoming processes need to query the modified content. Redirects have a direct impact on performance. Submitting only when necessary has improved our performance tremendously. On Tue, Aug 19, 2014 at 6:05 PM, Marc van Grootel < marc.van.groo...@gmail.com> wrote: > Hi France, > > Ok I get it now. No, really, because what your working on is very > similar to what I'm regularly dealing with at work (translation, xliff > etc.). I can also relate to your feeling that you need more control or > insight in what's going on in your code. I have been through this > journey too and sometimes I still find myself in a similar spot as you > describe. Especially when deadlines are breathing in your neck ;-) > > But I think that instead of looking for "technical" solutions to > insert more logging to see what's going on what you need is to break > up your code, bring more structure to it. There are many things going > on in this small piece of code.For starters each "case" warrants a > separate function. A function should be more or less about one thing > (Single Responsibility Principle). Doing this will also make the code > more testable. You can test each function separately. I admit this is > not always easy but it is key to keep your code under control. > > Also have a look at the Unit module which provides you with a way to > test each individual function with all types of arguments. You can run > it very easily from the commandline (e.g. basex -t test-files/). > During development of code immediately write these tests. You can even > adopt a bit of test driven design (TDD) where you write tests even > before the code works. Then you code until your tests pass. Best of > all, you will keep these tests for the lifetime of your code and > running them and seeing all of them pass will give you confidence in > your code (or find out that you broke something). These test cases are > also great documentation because they remind you of what a function > was supposed to do when you already forgot because you went on to > other projects. > > Another tip: when tackling something new and I'm not sure what > combination of XQuery functions I need I always start the GUI, load > the modules I'm working on and start experimenting. But once I have a > better idea I start writing tests. > > It's not easy but very rewarding (and writing tests after the fact can > feel very boring that's why you should do it while you work on the > code). Every time I neglect these principles, because, for example, a > deadline is near, it comes back to bite me later. In many cases it > resulted in throwing away the code and starting from scratch. > > Sorry, no instant gratification by pointing you to a "magic" module. > Still, I hope it helps you. > > Cheers, > > --Marc > > On Tue, Aug 19, 2014 at 11:12 PM, Andy Bunce <bunce.a...@gmail.com> wrote: > > If the goal is debugging > > .. another approach might be to think about Aspect Oriented Programming > > something like > > http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/ > > > > /Andy > > > > > > On 19 August 2014 18:05, France Baril <france.ba...@architextus.com> > wrote: > >> > >> Hi, > >> > >> I am hoping to use this for debugging. Our project is fairly complex > and I > >> use a controller function to apply multiple operations to content (each > of > >> these may use one or more function). When I get a 500 error, it's very > hard > >> for me to pinpoint the source of the issue. > >> > >> I can get the data from the form filled by the user and a few of the > >> redirect, but that only gets me so far, if I could track both the > function > >> names and the parameters for sub-functions, it would save me a lot of > time. > >> > >> Below is an example of what I call a controller... I use those when I > need > >> content to be saved before I can query it again for the next updating > >> operation. Each if the workflow step uses multiple sub functions that > are > >> not accessed through http and that are as far as I know untraceable. > >> > >> (: Transforms content to xliff for each language and export packages for > >> translation vendors :) > >> > >> declare %rest:path('/translation/create-package') > >> %rest:GET > >> %rest:query-param('menu-id', '{$menu-id}', '') > >> %rest:query-param('lang', '{$lang-in}', '') > >> (: The step that we were at when the function was called :) > >> %rest:query-param('step-id', '{$step-id}', '0') > >> %rest:query-param('package-number-in', '{$package-number-in}', > '') > >> %output:method("html") > >> %output:html-version("5.0") > >> updating function translation:create-package-controller($menu-id as > >> xs:string, $lang-in as xs:string*, > >> $package-number-in as xs:string, $step-id as > >> xs:string){ > >> > >> > >> ... > >> > >> let $workflow := <steps> > >> <step id="1" name="Add-ids">Add @ids for > >> en-us</step> > >> <step id="2" name="Health-check">DB health check > >> for en-us</step> > >> <!--step id="3" name="Check-keywords">Check for > >> keywords that may need to be replaced by prompts</step--> > >> <step id="3" name="Process-to-xliff">Process > files > >> to skeletons and xliff</step> > >> <step id="4" name="Register-packages">Register > new > >> packages in translation-management.xml... before deleting files with no > new > >> segments.</step> > >> <step id="5" > name="Old-content-to-target">Process > >> files in no-new-segment (could have different attributes or deleted > content) > >> to target lang.</step> > >> <step id="6" > name="Delete-no-new-segment">Deletes > >> no-new-segment xliffs that were processed in step > >> Old-content-to-target.</step> > >> <step id="7" name="Set-target-status">Sets > >> updatibility of target topic</step> > >> <step id="8" name="Export-and-zip">Export and > zip > >> files</step> > >> </steps> > >> > >> > >> ... > >> > >> > >> switch ($workflow//step[@id=$this-step]/data(@name)) > >> case 'Add-ids' return (:let $debug := > >> file:append('debug-create-pack-crash.xml', ' In Add-ids '):) > >> let $t := '' > >> return (admin:add-ids('en-us'), > >> > >> db:output($next-step-forward)) > >> > >> ... > >> > >> > >> case 'Set-target-status' return (:let $debug := > >> file:append('debug-create-pack-crash.xml', ' In > >> Set-target-status '):) let $t := '' > >> > >> return (for $lg in $lang > >> return translation:toggle-target-status($lg), > db:output($next-step-forward)) > >> > >> > >> > >> .... > >> > >> > >> > >> case 'Export-and-zip' return (let $zip := > >> translation:export-and-zip($menu-id, $lang, $package-number) > >> (:let $debug := > >> file:append('debug-create-pack-crash.xml', ' In > Export-and-zip '):) > >> return ((), > >> > >> db:output($next-step-forward)) > >> ) > >> default return ((), > >> db:output(admin:display-in-dashboard(<div><div class="l2" > >> style="color:red;">An error has occured, you should have been > redirected to > >> the export function before reaching this point. Default in switch > >> steps.</div>{app:get-beep-div-for-dashboard('error')}</div>))) > >> > >> > >> }; > >> > >> > >> > >> > >> On Tue, Aug 19, 2014 at 10:26 AM, Christian Grün > >> <christian.gr...@gmail.com> wrote: > >>> > >>> Hi France, > >>> > >>> I would also be interested if you'd like a functionality as proposed > >>> by Andy, and if you are interested in improving debugging your XQuery > >>> code, or if you think that such a function could also be helpful in > >>> productive code? Do you have some more input? > >>> > >>> Thanks, > >>> Christian > >>> > >>> > >>> On Mon, Aug 18, 2014 at 7:14 PM, France Baril > >>> <france.ba...@architextus.com> wrote: > >>> > Hi, > >>> > > >>> > I'm working on improving our tracking capabilities. I was hoping to > >>> > find a > >>> > function that would do the equivalent of what the code bellow does, > but > >>> > for > >>> > internal functions that are not called through the rest interface. > >>> > > >>> > string-join(for $name in request:parameter-names() > >>> > return $name || ': ' > >>> > || > string-join(request:parameter($name), > >>> > '; '), > >>> > > >>> > ' ') > >>> > > >>> > In short, I was wondering if there is way I can read the function's > >>> > parameters and their values without listing each one explicitly. > >>> > > >>> > I searched the documentation without success. > >>> > > >>> > -- > >>> > France Baril > >>> > Architecte documentaire / Documentation architect > >>> > france.ba...@architextus.com > >> > >> > >> > >> > >> -- > >> France Baril > >> Architecte documentaire / Documentation architect > >> france.ba...@architextus.com > > > > > > > > -- > --Marc > -- France Baril Architecte documentaire / Documentation architect france.ba...@architextus.com