Tell block madness!

Just wanted to post this for any newbies out there. I’ve run into more problems with tell blocks in AS Studio applications! I just got done fighting for an entire day with several problems that turned out to all be related to an enclosing tell block! :o

In regular AppleScript, I’m willing to bet we’ve all gotten a bit sloppy about what we put in a tell. Since the only real use is to talk to other applications, we go ahead and do a lot of “bookkeeping” in tell blocks, assigning variables and doing other business that really don’t need to be in a tell.

But in AS Studio, they will kill you if you do that. For example, I addressed a tell to a tab view item in a window and later had problems doing a date conversion (string to date) that worked fine in Script Editor. And manipulating button states can also be problematic(“on state” didn’t cause an error in an if statement, but being in the tell block killed its function). After re-writing so that the tell only included getting the contents of items in the tab view, and then doing all the other manipulations outside the tell, many problems were solved. :cool:

Of course, maybe I’m the only one out here that’s stupid enough to do things like that, but if so, then I’ll keep the pie on my face long enough to prevent someone else looking stupid too!

Hey, Kevin.

You’re certainly not the only one who has had problems with this. I’ve pointed out to dozens of people the importance of keeping code clean and consistent… and tell blocks are one place where you can not afford to try to cut corners with your code. The difficult part is, that you can not always know up front whether a bit of code will be adversely effected by placing it inside of a tell block. There are a lot of ways that a given bit of code can be interpreted, and there are certainly many times when a bit of code can be placed in a tell block and it will perform just fine. BUT… is that to say that we SHOULD put it in there? In my opinion, no. For years now, I’ve been watching others bang their heads over the simplest of problems, because they have not taken the time to really look at the code they’ve written to see if it makes sense. Remember, we’re writing a language, not just a bunch of chicken scratches that somehow magically work. Writing good code… especially in applescript… requires only that you write out the story that you want your application to follow. What I’ve found in my time spent scripting, is that it often saves me time and frustration to simply clarify what it is I want to do, and then carefully go through each necessary step to accomplish the goal. Sounds simple, but we often get carried away in “streamlining”, condensing code, and trying to get the job done in as little time as possible. When we get off on these idealistic tangents, though, people forget that the code should just be written in such a way that it gets the job done while being clear, smart, and modular. While it sounds easy and convenient to say that up here on my soap box, it’s really the truth I think, and I see people getting way ahead of themselves a lot of the time trying to ‘change the world’ in a day rather than just slowing down and doing things correctly.

I have pointed out countless times to people that they have code in places that it shouldn’t be. Often it is within tell blocks, and although it sometimes works I always try to point out the importance of re-writing the code so that it is not within the block, just on principal. While it may seem trivial to someone who’s just starting out with AS and who has never had a problem with a tell block conflict, it is an important concept and should be learned for many reasons. While style is important, I think it is of even greater importance to write good code on principal. By writing clean, literal code all the time you are speaking the machine’s language more precisely, leaving yourself less open to the chance of your intentions being misunderstood. Getting the job done is no substitute for getting the job done right.

For example, a common pitfall is using a command or calling a subroutine from inside of an application tell block…

tell application "Finder"
	set theNewWindow to (make new Finder window)
	someSubroutine()
	close theNewWindow
end tell

Because the finder has no idea what a ‘someSubroutine’ is, it errors. If “someSubroutine()” were replaced with something a bit more benign like “beep”, it would function fine and you’d never know the difference. Of course, you could do “my someSubroutine()” and all should be well, but that’s beside the whole point I’m trying to make. Many of you might argue that using “my…” would be appropriate, and I will concede to that in this simple case. But, it’s also important to think about why using it might NOT be the best option, considering the broader concept of writing clearer code.

Why not just do this?..

tell application "Finder" to set theNewWindow to (make new Finder window)
someSubroutine()
tell application "Finder" to close theNewWindow

The script size change is negligible, the script is easier to read, and at no time are you in question of whether any conflict might occur because of a tell-block conflict. While there are certainly occassions where this may not be appropriate or reasonable, it illustrates the importance of being clear in your intentions. Not only will you be able to read through this tomorrow or 2 years from now and see quite obviously what it’s intentions are, if you have a problem with it the likelihood of finding the problem quickly increases because you’ve already eliminated the more obvious obstacles by simply writing good code from the beginning.

As you’ve said, Kevin, in ASStudio we also often run into tell-block conflicts with object references. I’ve seen many occassions where people get errors referencing objects because of what you describe. Most of the time, it is newer users who’ve not had the pleasure of staying up until 2 in the morning :stuck_out_tongue: looking for something so simple as a tell-block conflict that they never thought of or considered. While it makes perfect sense to an experienced scripter, someone who’s never learned the lesson wouldn’t have a clue that they even needed to look for such a gremlin.

Ultimately it comes down to learning how to write your code so that it follows as logically as possible with how the compiler will try to interpret what you as a programmer are telling it. By placing any call inside of a tell block that doesn’t need to be there, you’re breaking the logical flow of the code and leaving yourself open to unforeseen problems both now and into the future. As you write more and more scripts, you train yourself to write in a certain style. Training yourself to write in a way that makes no sense (other than by sheer luck of not encountering a truly logical boundary) leaves you vulnerable to hours of brain-racking, head-banging, hair-pulling frustration. I’ve been preaching the importance of writing clean code since I started coming here, and I still think it’s the cause of 80% of the problems users have with their code. While it takes a long time to learn all of the intricacies of any language, it is important nonetheless to start practicing good code-writing skills the day you start writing code.

Applescript is so pleasant. It’s pretty. You write it and it flows like poetry… it often even looks like poetry, because of it’s english-like terminology and user-friendly focus. Scripters should remember this, viewing their creations not just as work… but as works of art. People often post these insanely messy jumbles of code that look scary and unappealing. I rarely bother to read code samples that are obviously not thought-out at all. Nothing personal, I just don’t have the time to point out to people that they’re not focused, are rushing into something that’s obviously beyond their skill set, or that they’re just lazy. If you’re code is clear and says only what it means, it is always beautiful and a pleasure to read. And, on top of the benefits of having good form, you’ll end up with a product that also has better function.

Just my two cents for the day, take care all…
j

Jobu,

Thanks for the reply. You hit the nail on the head. It IS nicer to have clean, focused code, and the pleasant side effect is fewer errors, less frustration, and (important to me, since I ususally publish the source with my apps) easier to read and make sense of.

This last stupidity of mine started innocently, I swear. I knew very well what I wanted to do, and in fact started to write it all out with long references (set something of something of something of something) and tried to cut corners and take all the long references out and replace it will an enclosing tell block. In writing clear code I think it’s also important not to have long references littered all over the place. If you only need one item, a long reference is fine, but if you’re accessing several items from, say, “view of tab view item 1 of tab view 3 of window “such and so”” it makes more sense to set up a tell block, use local variables to get all the items at once, and then have a block of code that makes used of all those items (at least that’s my opinion).

While we’re on the subject, I am a firm believer in stating local variables, too. I hate “invented” variables that are used only once and never referred to again. It’s all too easy to say “set myText to contents of text field “blah”” and then use it in some next line of code and then never use it again. If you need to do those kinds of things, create one item, call it tempText and declare it at the beginning of the handler as “set tempText to “”” and stick a comment next to it that says “–used for temporary storage of various items”.

And if I were writing C or C++ code, I’d rage and scream about global variables (or in AppleScript Studio terms, “properties”) but there really isn’t another way to do things in AppleScript Studio. It would be nice if part of the mechanism of AS Studio, you could not only hook up an AppleScript name to a an item in Interface Builder, but also tell it to send a given set of variables. But I realize that won’t happen, so I’m not tripping on it. All of the work arounds for passing properties or globals between scripts in AS Studio suck. Try writing a document based app where you need to pass preferences or other global values and you’ll see what I mean. You shouldn’t have to kludge a solution for that, but right now there’s no other way.

Anyway, I just hoped that posting the original post would save some noob from making the same mistake.

I will agree with this, but I also recommend taking this a little further. Long references are quite difficult to manage, and become even more of a burden when you make changes to your interface and then have to go back through and recode all of your references. In all of my significant apps, I set up an initialization subroutine which executes right after the nib awakens. It goes through and creates unique static references to all of the primary objects and containers I will be regularly referencing in my code. For example I might do something like…

property Obj_Main_Preferences_General : "" --> A reference to the general preferences tab view item

on launched theObject --> connected to the application object/File's Owner
	initialize_objects()
end launched

on initialize_objects()
	set Obj_Main_Preferences_General to tab view item "General" of tab view "Preferences" of window "Main"
end initialize_objects

Now, I only once in my code have to write out all of those long references, and everywhere in my code that I need to reference that tab view item I just substitute ‘Obj_Main_Preferences_General’ for that long-winded reference. I find that this GREATLY reduces the risk of me mistyping a long reference. I can also use references I’ve already established to create subsequent references. This can also be done in an awake from nib handler attached to each individual object, but that can get complicated and ugly if you’re setting up references to a large list of objects. Having one subroutine where all of your initilaizations are done is clean and easy to evaluate later.

It is important (I think) to keep some continuity between the names I use in my interface and the names I assign to variables which reference them in my code. People often use cryptic names for object references that eventually become confusing, especially if your project takes on a life of its own and becomes a bigger one than you had originally imaged (that’s never happened to any of us, has it? :lol:). For example, if you’re setting up a reference to [ text view “Text” of scroll view “Editor” of box “Editor” of split view “Library” of window “Chronicle” ], why on earth would you reference it as something like “textBox” or “T_EE_C4”. Instead, use something like “Chronicle_Library_Editor_Text”. This allows you to quickly look at the reference anywhere in your code and and gives you a mental signpost for knowing which “physical object” you’re talking about. This may not seem important, and may not seem applicable to a simple app with only a half dozen objects, but it’s the conscious effort of learning to do things all of the time in one precise way that is key. Also remember, that this is just my way of keeping tabs on things. Everyone is of course free to do things however they wish to, but creating one logical method of doing things and then always sticking to it sure seems to save me time and frustration.

j

When I wrote ColdFusion for a company that I worked for, my boss (who wrote the original web application) was what we called a “cowboy coder.” He had no formal training in programming or writing “clean” code and so wrote (what to my eyes) was a tangled mess of spaghetti code. When my team re-wrote the code (necessary, not just an exercise on my part) because we had clients that wanted different functionality, we became aware of a ColdFusion user group and started attending meetings. There, we learned about a method of writing structured web code (not a phrase you hear every day) in a style called “fusebox”. The idea was to create a single page for the site that contained all the logic for the page views and selected what to show based on a string passed on the URL (the “?action=myaccount” stuff you sometimes see in URLs).

This allowed us to write modular code so that we could “swap out” a section for a given client and write a custom section for them.

My point isn’t to tell all about my code writing history. I’m suggesting that perhaps we need to get a bunch of AS coders together and discuss a set of “best practices” for writing AS and specifically AS Studio code. Realizing they aren’t binding, it would still be nice to have a “style sheet” of how most of us agree it is best to code for newbies to get off to a good start to begin with. That way we aren’t spending time re-hashing the same lessons and they have the advantage of our experience to leverage their way into more advanced coding faster.

Just a thought.