Article
· 2 hr ago 4m read

Learning ObjectScript as a New Developer: What I Wish I Knew

I joined InterSystems less than a year ago. Diving into ObjectScript and IRIS was exciting, but also full of small surprises that tripped me up at the beginning. In this article I collect the most common mistakes I, and many new colleagues, make, explain why they happen, and show concrete examples and practical fixes. My goal is to help other new developers save time and avoid the same bumps in the road.

 

1. Getting lost among system classes and where to start

The issue: ObjectScript/IRIS ships with many system classes and packages (%Library, %SYS, %Persistent, %SQL, etc.). As a new dev, it’s hard to know which class or pattern fits a task. I remember trying to find an appropriate persistent class and being unsure whether to extend %Persistent or use a registry-type class.

Why it matters: Picking the wrong approach early makes code harder to maintain and integrates poorly with IRIS features (indexes, security, SQL).

Tip: Start from the concrete need (store records? expose SQL? share objects across processes?) and then search the Class Reference for the relevant capability (persistence, indexes, collections). Use Studio or the InterSystems VS Code extension to browse classes interactively and inspect examples.

 

2. Documentation overwhelm: not knowing the right keywords

The issue: The docs are comprehensive, but if you don’t know the correct class name or term, searches return many unrelated pages. Early on I often spent a lot of time because I didn’t yet know the canonical terms.

Why it matters: You waste time and might implement suboptimal patterns.

Tip:

  • Search the Developer Community for practical examples (search by “persistent class example”, “ObjectScript transaction TSTART example”, etc.).
  • Use the VS Code InterSystems extension, it can jump directly to class definitions.
  • When searching docs, combine class names and actions: e.g. "%Persistent property index example".

 

3. Forgetting .. for local method call

The issue: Calling a method of the same class without .. results in a call not being recognized at runtime.

Wrong:

Class MyClass Extends %Persistent { 
   Method DoWork() 
   { 
       Do Hello()  // wrong: this is not a local method invocation
   } 
   Method Hello()
   { 
       Write "Hello", ! 
   } 
}

Right:

Method DoWork() {
   Do ..Hello()  // correct: local method call 
}

Tip: When you get “Unknown routine” errors for methods you see in the class, check whether you used .. for self-calls.

 

4. Confusing globals and local variables

The issue: ObjectScript distinguishes globals (persistent across sessions, e.g. ^MyGlobal) and local variables (in-memory, scope-limited). New developers frequently use one when the other is intended.

SET localVar = 10    // exists only during the current process/session
SET ^globalVar = 20  // persists in the database across processes and sessions

Tip: Use persistent classes for data that should be stored long-term. Limit use of globals to very specific low-level needs or when you understand consequences.

 

5. Hardcoding globals instead of using persistent classes

The issue: My instinct at first was “quick and dirty”: write to ^MyGlobal directly. That works, but it bypasses class-based benefits: schema, indices, SQL access, and safety.

Better approach:

Class Person Extends %Persistent 
{ 
    Property Name As %String; 
    Property DOB As %Date; 
}

Tip: Prefer %Persistent classes for application data. They give you a cleaner model and integrate with SQL and indexes.

 

6. Ignoring transactions (TSTART / TCOMMIT)

The issue: Developers sometimes perform several writes thinking they are atomic. Without explicit transaction control, partial failures can leave inconsistent data.

TSTART 
// multiple updates 
TCOMMIT

Tip: Identify logical units of work and wrap them in transactions. If something can fail halfway, use TSTART / TROLLBACK / TCOMMIT. Keep in mind that IRIS supports nested transactions: multiple TSTART calls increase the transaction level, and all levels must be committed (or rolled back) before changes are final.

 

7. Misunderstanding SQL options: Embedded SQL vs %SQL.Statement

The issue: Embedded SQL (UPDATE, SELECT blocks inside ObjectScript) and the %SQL.Statement API are both available; choosing without knowing pros/cons can cause awkward code.

Guideline: Use Embedded SQL for fixed/static queries inside routines; use %SQL.Statement when you need to build and execute SQL dynamically.

 

8. Skipping proper error handling

The issue: Not using TRY/CATCH or signaling errors properly makes debugging and reliability harder.

TRY 
{ 
   // code that may fail 
} CATCH ex 
{  
   Write "Error: ", ex.DisplayString(),! 
}

Tip: Wrap risky operations (I/O, external calls, dynamic SQL) with error handlers and log informative messages.

 

Final notes

Early on I wrote globals for convenience and later spent time refactoring to persistent classes. That refactor taught me the value of designing data models up front and using the tools IRIS provides. My best habits now: small experiments, frequent searches on Developer Community, and keeping transactions and error handling in mind from the start.

If you’re new: treat your first few tasks as experiments, create small persistent classes, try simple Embedded SQL, and use the Management Portal and VS Code browser to inspect system classes. Ask questions on the Developer Community; many others had the same “gotchas.”

For more: check the official ObjectScript documentation and the Developer Community for examples and patterns.

 

This article was reviewed and edited with the assistance of AI tools to improve clarity and grammar. The experiences and suggestions described are my own.

Discussion (3)2
Log in or sign up to continue

Combining what you said about error handling and transactions and also returning a status, a very basic outline for a lot of methods could be something like:

try{
    TSTART
    //Do stuff here
    TCOMMIT
    return $$$OK
}
catch ex{
    if $TLEVEL > 0{
        TROLLBACK
    }
    return ex.AsStatus()
}

Some of us who write articles could do a better job of making this easier for you too, though. We like to use short forms of certain things, like {} and [] which are ##class(%Library.DynamicObject) and ##class(%Library.DynamicArray). I try to remember to use the latter in my articles just because it makes it easier to find the thing I'm talking about in the documentation. There are cases like that which are technically correct, but make it harder for beginners to learn.