11 Replies Latest reply on Mar 15, 2017 10:22 AM by Laubender

    Your opinion on best practices.

    williamadowling Level 4

      Over the 2 and a half years I've been writing javascript, I've changed my practices time and time again as I've learned new techniques or encountered unforeseen problems with other techniques.

       

      At this point, I'm essentially writing everything as small function modules and then doing "running flag" (term coined by Silly-V) validation checking like so:

      function doSomething(input)
      {
           //do something
      }
      
      function doSomethingElse(input)
      {
           //do something else}
      }
      
      var valid;
      
      if(valid)
      {
           doSomething(input)
      }
      
      if(valid)
      {
           doSomethingElse(input)
      }
      

       

      The question I want to ask of you knowledgeable folks is whether you think it's better to do the validation within the function and always return a boolean and just redefine global scope variables (or object properties) from inside the function like so:

      function doSomething(input)
      {
          var localValid = true;
          var value;
          //do something
          //get value
      
          if(value != undefined)
          {
              globalObject.property = value;
          }
          else
          {
              //log some error
              localValid = false;
          }
      
          return localValid;
      
      }
      
      var globalObj = {};
      
      var valid = true;
      
      if(valid)
      {
          valid = doSomething(input);
      }
      if(valid)
      {
          valid = doSomethingElse(input);
      }
      

       

      or return a value from the function and do the validation after the function has returned the value, like so:

       

      function doSomething(input)
      {
          var value;
          //do something
          //get the value
      
          return value;
      
      }
      
      var globalObj = {};
      
      var valid = true;
      
      if(valid)
      {
          globalObj.property = doSomething(input);
      
          if(globalObj.property != "correct value")
          {
              valid = false;
          }
      }
      if(valid)
      {
          globalObj.otherProperty = doSomethingElse(input);
      
          if(globalObj.otherProperty != "correct format")
          {
              valid = false;
          }
      }
      

       

      I'm sure the correct answer is "it depends". If that's the case, do you have certain desired return data types that you do one way, and others you do another way?

        • 1. Re: Your opinion on best practices.
          Silly-V Adobe Community Professional

          This is a great question! It is useful sometimes to have functions which work on an input to produce an output only, and other times some which change outside-scoped variables, and any mix of those.

          With a method of only processing output of functions to consider how successful those functions are, you don't have the brain-racking that comes with keeping track of the global variable names, and you will likely know the exact cause of your error because you'll be alerted to the failing line which would correspond with a specific function at hand.

          If you change global variables and keep a restricted name list for yourself so that you don't use them in other parts of your code for other things, it may be just as effective, I'm not sure. I do think that changing outside vars is what you want to do when you're logging outcomes of some processes which do not require you to halt the script, such as try-catch blocks.

          • 2. Re: Your opinion on best practices.
            williamadowling Level 4

            Well said. that's good advice.

             

            The frustrating part about all of this is that most of the time I'm checking for errors that shouldn't exist in the first place. For example, if i have a function that simply looks for an existing layer, creates the layer if it doesn't exist, then saves that layer to a variable.

             

            That kind of function should NEVER give me an error. but because of the unpredictable MRAP errors, i have to assume that any line of code can fail for any reason and that's turned my scripts into a complete rats nest of very short try/catch blocks because it's the only way i can produce meaningful error messages...

             

            Quite frustrating.

            • 3. Re: Your opinion on best practices.
              Silly-V Adobe Community Professional

              So you get MRAPs with just trying to add layers in? Say, are you guys all on CS6 still? I've gotten PARMs but not yet for going over layers, but I've been on CC for the last couple of years now.

              • 4. Re: Your opinion on best practices.
                williamadowling Level 4

                adding, removing, or reading properties of layers/swatches cause the most mrap errors by far.

                 

                We're currently on CC 2014, but IT is insisting we upgrade to 2017 within the next couple months (not stoked about that because i've seen big issues with every new rollout.. and if my scripts stop working because of an update to illustrator it's going to be my fault...)

                • 5. Re: Your opinion on best practices.
                  Qwertyfly... Level 4

                  whenever you do one of the major updates, make sure you uncheck the option to delete old versions of the software.

                  at least then if they break the software, or your workflow you can just go back to the version you used the day before.

                   

                  Warning: I have been getting more parm errors then ever before, thanks to an update to CC2017.

                   

                  and I'll second that Swatches and Layers do tend to be the major offenders

                  • 6. Re: Your opinion on best practices.
                    Laubender Adobe Community Professional & MVP

                    Hi Qwertyfly,

                    I'm just a casual guest here in the Illustrator Scripting forum.

                     

                    Coming from the InDesign side of scripting I wondered what a PARM error or MRAP error is in principle.

                     

                    I found this one here at Stack Overflow:

                    javascript - Why script will sometimes launch ExtendScript Toolkit & just stall - Stack Overflow

                     

                    So it seems, that:


                    PARM is issued on Windows

                    MRAP on Mac OSX

                     

                    Are these "classes" of errors the same?

                     

                    I just searched both terms a bit. But I did not find out what the acronyms PARM or MRAP are actually mean.

                    The following source gave a hint on the 1346458189 ('PARM') or 'MRAP' error number.

                    http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/pdf/illustrator/scripting/Readme.tx t

                     

                    Are there more PARM or MRAP errors like this with different numbers?

                     

                    Does it help to go for a pattern like that using an selfexecuting anonymous function?

                    (function(){}())

                    And wrap the whole script into the two curly brackets {} ?

                     

                    (
                    function()
                    {
                    // Here goes the whole script code:
                    // …
                    }()
                    )
                    

                     

                    Does something speak against using such a pattern for Illustrator scripting?

                     

                    I'm just curious, because I'm not much into Illustrator scripting and want to avoid some pitfalls if possible.

                     

                    Regards,
                    Uwe

                    • 7. Re: Your opinion on best practices.
                      Silly-V Adobe Community Professional

                      The PARM/MRAP can be caused by some invalid script commands, but what we notice is these being caused by simple script 'reads'. For example, when iterating through document items, some will already have "Illustrator internal Error..." listed as the value of some properties of those items. In those cases, you could say that somehow within the scripting session those pageItems became 'corrupt'. I had a script to do years ago which I had to get help with, and the resourceful programmer who helped me was able to solve such an issue by duplicating every suspect item (and deleting old item) before working on it.
                      Some workaround techniques from this forum and the internet include: copying/pasting items or nudging them with a translate to get those properties working again.

                      • 8. Re: Your opinion on best practices.
                        williamadowling Level 4

                        You are correct. MRAP is mac and PARM is windows, but as far as i know they are the same error.

                         

                        Thanks for posting that readme file. I had not seen that before, but everything it says is true. Avoid global variables at all cost. As a general practice, many around here, myself included, wrap every script inside a container function (though I cannot speak to whether the IIFE in your example would work better..). I use the following function wrapper in every script i write:

                         

                        function container()
                        {
                             //script
                        }
                        container();
                        

                        Some issues identified as "more frequent than others" (the errors do seem to be truly random and generally non-repeatable), are:

                        • working with layers and swatches, most notably, creating or renaming layers or swatches
                        • constantly initializing variables inside a loop (see below)

                         

                        Some speculate that the errors occur less frequently if you initialize a variable outside of a loop and then change the value inside the loop like so:

                         

                        var someVariable;
                        for(var i=0;i<10;i++)
                        {
                             someVariable = docRef.textFrames[i];
                             someVariable.contents = "blah blah " + i;
                        }
                        

                         

                        I've not personally noticed a difference when using one or the other, but people around here who are much smarter than me say it helps. And it's a very easy concession to make. It's not extra work, just a change in habits.

                         

                        Ultimately, in my 2+ years writing javascript for illustrator i've concluded that there is no rhyme or reason to the random MRAP/PARM errors. (though as Silly-V said, sometimes you may get the error when trying to do something the script can't, like delete the last artboard in the document or create 101 artboards).

                         

                        Best of luck to you. We're all here to help if you have questions or issues along the way.

                        • 9. Re: Your opinion on best practices.
                          Laubender Adobe Community Professional & MVP

                          Silly-V  wrote

                           

                          … In those cases, you could say that somehow within the scripting session those pageItems became 'corrupt'. I had a script to do years ago which I had to get help with, and the resourceful programmer who helped me was able to solve such an issue by duplicating every suspect item (and deleting old item) before working on it.
                          Some workaround techniques from this forum and the internet include: copying/pasting items or nudging them with a translate to get those properties working again.

                          Hi Silly-V,

                          thank you for this. Highly appreciated!

                           

                          It seems that sometimes DOM objects cannot be "resolved" ?!

                           

                          What do I mean by "resolved"?

                          "resolved" is a technical term that is more with InDesign and not at all with Illustrator, I think.

                           

                          In Illustrator a DOM object like Document has no getElements() method—unlike InDesign. getElements() would drill through to the actual item and reveal all its properties and methods. Actually touching them if you loop the returned array.

                           

                          I like to paraphrase the situations you are pointing to so that you get an idea if I grasped it right:
                          With Illustrator scripting it seems that sometimes one has to "revive" a DOM object by "copying/pasting" or "nudging" it to get it orderly to the stack of accessible objects. That it "remembers" its properties and methods.

                           

                          Thanks,
                          Uwe

                          • 10. Re: Your opinion on best practices.
                            Silly-V Adobe Community Professional

                            If your MRAP is caused by DOM art object problems, then yes, those techniques could be tried.

                            My first encounter with these errors in this way was during a swatch processing script which batch-processed documents and changed something about the colors. The file batches would be typically around 100 files and I noticed these errors start to come up around 20 files in. At first I dealt with it by wrapping in a try/catch and closing/re-opening my problem document. When it reopened, most of the time the error would no longer be present... but inevitably, as the script processed more files in the batch, the errors would re-emerge and become more common. Soon the document which was auto-reopened now had to be re-opened several times until it got 'lucky' and saw no error. Eventually toward the end of the batch, the errors got so numerous that the script completely hung up.
                            This was not only a property-corruption error, but it seemed to be caused to exacerbated by the batch aspect of that script, where files would be repeatedly opened and closed.

                             

                             

                            This was on CS5 years ago. Since then, to fix this batch-related object-property error, I was able to arrive at the current workaround I use to this day: open all the batch files at one time, process them all, then close them all - or even use the "quit" command for large batches which bypasses any issues with file-closing and auto-closes all files which are saved. They say it's good to restart AI between large batches anyway.

                            1 person found this helpful
                            • 11. Re: Your opinion on best practices.
                              Laubender Adobe Community Professional & MVP

                              Hi William,

                              thank you for your points.

                               

                              Hm. Maybe we could check the script engine by using $ ?
                              What kind of variables are already in use, what methods are exposed?

                               

                              Dirk Becker did some groundbreaking work with that:

                              summaryDifference.jsx script for Adobe InDesign

                               

                              The title says "for Adobe InDesign", but it should work for all apps using ExtendScript.

                               

                              Also here something more about using $ :

                              Re: How to keep track of all the classes/methods/properties created in a long script

                               

                              Regards,
                              Uwe

                              1 person found this helpful