Disclaimer and License

Opinions expressed here by Tim Tripcony are his own and not representative of his employer.

Creative Commons License
Tip of the Iceberg is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at timtripcony.com.

Unless otherwise explicitly specified, all code samples and downloads are copyright Tim Tripcony and licensed under Apache License 2.0.

Search

What the Quote?

"Woe is me, I have no bitches... it's a paradox."

Laura Tripcony

"...and I swallowed my gum, 'cause I thought it was the Apocalypse."

Jennifer Holland

"I'm not going to forget that for the same reason scars don't heal."

Tim Tripcony

« the next step in the journey | Main| org.openntf.xsp.extlib »

Needle in the Stack Part 2: talk to data, not to components

Category xpages stackoverflow
More and more XPage developers are turning to stackoverflow to seek community assistance with questions they have about developing XPage applications. This ongoing series will provide additional commentary and insights into the answers I have provided on the site that members of the community have found to be useful.

Part 2: talk to data, not to components

This post is a deeper explanation into this answer and the brief discussion that followed.

First, an analogy. Let's assume, for the sake of discussion, that you have a boss. We'll call him Bob. Bob is like a lot of bosses: if you make him successful, he makes you successful. You also have a coworker. We'll call him Tom. On your first day, you saw another coworker ask Tom a question; Tom didn't know, so he asked Bob. Bob's the boss, so naturally he had the right answer. Tom returned to his cubicle and gave the information to the person who needed it. Everybody was happy.

Ever since, when you need to know something that Bob is sure to know, you ask Tom, because you've already seen that approach work. Likewise, if you have information that you know Bob needs to be made aware of, you tell Tom. You keep getting the information you need, and so does Bob, so on the surface it seems like everything's fine. But occasionally you wonder whether there might be a more efficient way. After all, Bob's office is right across from your cubicle, and sometimes Tom is on a different floor of the building; it takes a while, but if you start at the top floor and work your way down, checking every office, cubicle, and conference room, sooner or later you find him. This approach always works, but somehow just seems less than ideal.

Then one day, you can't find Tom. You know he's somewhere in the building, but nobody knows how to find him. You check every floor, and a few people mention that they've seen him, but for some reason each time you get to where he was, he's already somewhere else. You're starting to panic, because a customer is waiting for a solution, and you know Bob has the information they need. If only you could just find Tom, everything would be all right.

Meanwhile, Bob has been sitting in his office the whole time, perfectly accessible from your original starting point. Maybe you should just go talk to him directly.

This story probably seems silly, because it is. But we all do it. Every time we call getComponent(), we're trying to find Tom.

In any application, data is the boss. The user interface can have a strong influence on whether the application will be considered successful, but ultimately it's the data that decides. If the application allows the users to create and retrieve the data necessary to achieve the goal of the application, it's a win. If that doesn't happen, it doesn't matter what the app looks like or does: the application has failed.

In XPages, then, the components that ultimately matter the most are those that are bound to some form of data. This could be NSF-specific types of data, such as items on a document or column values of a view entry, JSF-specific types of data, such as a scoped variable or managed bean, or something entirely arbitrary, such as a YQL query, web service, REST API, or some other custom source of data. Any component that doesn't have a relationship to data is essentially just user interface fluff. That fluff might be necessary in order to keep users happy in interacting with the data, but it only exists to support use of the components that do interact with data. If you tell one of those components it should have a new value, it's just going to go change the data it's bound to. Similarly, if you ask it for its value, it doesn't intrinsically know; it has to go ask the data. Hence, you might as well just talk to the data directly. Components are there to allow users to interact with data. If your code needs to interact with data, talking to the components just introduces an unnecessary "middle man", and an inefficient one.

Locating components programmatically is one of the most computationally expensive operations you can perform in the core XPages runtime, short of interacting directly with the "old" Domino Java API (the lotus.domino package, the bulk of which was written when I was in high school and therefore suffers from design decisions made prior to the last 16 years of discovering better ways of writing Java). Conversely, the variable resolver always has a direct pointer in the requestScope to any data sources that are valid in the current context. Domino doesn't have to traverse a hierarchical tree structure, performing a string equality check against a property of every node in the tree (which is how components are located) in order to find a data source... it can just grab it directly out of a map.

So my advice is to get out of this habit...

getComponent("fieldName").setValue(newValue);


...and start doing this instead...

currentDocument.setValue("fieldName", newValue);


Each instance of that pattern will perform more efficiently. It won't break if, for any reason, the component you would otherwise have tried to locate is now gone or its ID has changed.

But there's also a bonus reason. It only affects one use case, but of all the questions that I get asked about XPages, this is by far the most frequent:

"How can I reach into a repeat control from outside it?"

And here's the answer: don't.

I know that sounds snarkastic™. But it's simply the most succinct form I've found for the best answer to that question. Chances are likely that, if you're trying to locate a component inside a repeat control from a component outside of that repeat, it's because you want to either retrieve or update its value. Don't. Talk to the data. If you change the data that component is bound to, the next time the component renders, it will have the new value. If you retrieve the value directly from the data, then you don't need the component. Either way, the component is an unnecessary middle man in whatever goal you're trying to accomplish. And, based on the frequency with which I see this question, if you haven't already encountered this pattern, at some point, you will. So hopefully this diatribe will save you the frustration others have experienced because you'll remember there's an easier way. If you let each component talk directly to data, they never need to talk to each other.

Unless you need to tell a component to actually do something, like telling a dialog to show() or hide(). Then you're sort of stuck with getComponent(). But only then.

Here ends the reading.

Comments

Gravatar Image1 - Tell Bob that if he needs me I'm at Dunkin Donuts with Tom.

Gravatar Image2 - Thanks Tim ... good practice and good of you to share. Keep them coming!

- Paul

Gravatar Image3 - This is indeed one of the best tips I've seen lately. A few months ago I was working on a big xPage project and for 'some' reason the application started to became slower and slower everytime we added a little feature.

We couldn't find out why a little feature introduced such a big performance decrease. So one day a colleague found a post about using this.getParent() intead of var c = getComponent(x); var v value..

So we started to rewrite the code to remove all the getcomponent() calls wherever possible and guess what. The performance increased drasticaly.

So from a real world I example I can agree on

"This story probably seems silly, because it is. But we all do it. Every time we call getComponent(), we're trying to find Tom."

Gravatar Image5 - But what about Tom? What is he going to do now that you are by passing him and going straight to Bob? What if he develops low self esteem? Starts drinking and smoking and hanging out with .NET developers ?

It's a slippery slope. A very slippery slope !!!


Gravatar Image6 - Well said.

Gravatar Image7 - Great tip. I was able to try your tip in practice today and, guess what, it works!

Gravatar Image8 - Very snarkastic!


Gravatar Image13 - Think twice before you speak, because your words and influence will plant the seed of either success or failure in the mind of another.Emoticon

Gravatar Image14 - I admire what you have done here. I like the part where you say you are doing this to give back but I would assume by all the comments that this is working for you as well.

Gravatar Image15 - You have impeccable writing skills! You make some valid points with which I agree and I think this is really great reading material. Thank you.
Emoticon Emoticon

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)