• user warning: Unknown column 'u.signature_format' in 'field list' query: SELECT c.cid as cid,, c.nid, c.subject, c.comment, c.format, c.timestamp,, c.mail, c.homepage, u.uid, AS registered_name, u.signature, u.signature_format, u.picture,, c.thread, c.status FROM comments c INNER JOIN users u ON c.uid = u.uid WHERE c.nid = 26485 AND c.status = 0 ORDER BY c.cid LIMIT 0, 50 in /var/www/ on line 991.
  • warning: file_get_contents( [function.file-get-contents]: failed to open stream: HTTP request failed! in /var/www/ : eval()'d code on line 4.

Seek and you shall find

by Thibaud Arguillère

At first, I had the idea to name this article "If you seek me, you will get me." But it was a bit too easy. And, after all, not that funny (and I wanted a funny title). I looked at something else and found "Seek me, get me". But… removing a couple of words doesn't make it any more funny. That's why I finally decided upon a title that is not funny. It was a painful decision, but somebody had to make it and I was alone in my head at this time. So, "Query and Find" came up to my mind. Hmm. No. Still not working. Even worse: One could think I'm going to talk about the database engine, while I'm actually talking about the "Find in Design" functionality.




At the end, "Seek and you shall find," even it does not make you laugh, makes the subject crystal clear and you immediately know what this article will be talking about1.


A little oversight

During the developer conferences in past years, I didn't talk that much about this topic, which used to upset the people in charge of this feature in the R&D department, who never hesitated a second to let me know their feelings with scathing and unkind remarks. "Well well, yeah, OK, the new Web server in 4D v13 is very powerful and so cute2, but have you ever ask it to find all the dependencies of a method?" Or "Good point to insist on PHP Execute, sure. But it doesn't execute any query on unused objects in your code, does it?"


And they're right to vilify me, because ever since 4D v11 SQL, the Global Find & Replace - aka GFR - has evolved quite a bit, with a bunch of new features in each new version. It is stating the obvious to say that prior to v11, some of us used… What was it called? Let me try to remember… Ah, yes, 4D Insider to search in their developments. Even me, when I moved to v11 (and I was not working for 4D at the time), I had to face the absence of Insider. Sometimes, there are constraints that lead to disappearances. Hey, remember Betamax tapes? They're not on anyone's radar



One needs to face the Reality Principle. Not in its strict Freudian way4, but in the "since it's no longer here, I'll do without" way. And this means the GFR functionalities must be used. I don't want to just copy & paste the documentation here, but instead I'd like to insist on some points, including the two major new features of v13 in this area.


Let's start with a reminder. The GFR dialog has been revamped in v12, so one can naturally build the query: "I search for a variable whose name starts with INV, and whose parent was modified today":




I love when a query can be expressed that way. Not so long ago, I even found myself expressing the query aloud, without even filling the dialog. Which created an awkward moment when - in front of my colleagues from the open space - I insisted: "Please, 4D, find the constant whose name is a string variable". The day Siri is built into 4D, these embarrassing moments will become history.

Fighting futility
I don't spend time on the result window, which lets you to manipulate the list, to remove rows, or to "replace in content." If you didn't know about this, just take a walk around this window. However, here's a reminder of a very interesting feature appeared in 4D v12 (22 months ago): The ability to search for unused objects. You can see this feature in the screenshot, at the beginning of this article: "Find Unused Methods and Global Variables" and "Find Unused Local Variables." We all regularly clean up our code5. Finding - and deleting - unused local variables must be part of this cleaning.


That said, be careful when using it. It's about variables explicitly declared (C_TEXT, …), and never used. If you initialize an undeclared variable, for example you just write $tot:=0 and the method never use $tot, it is not seen as unused, while, well, it is unused, isn't it? Good point, I'm going to talk about this with the R&D people who are just a few seats away from me.


Finding and deleting unused methods is also an excellent way to clean up your code. Having unused methods is something very common. But, think about it: If the method is unused, why bother with? Why take the risk of a compiler error with a method that will never be called? Why weigh down the code and find ourselves one, two, five years later with dozens of unused methods that we're afraid to delete? That encumber us, bother us, and pollute the whole application? Delete those methods! No mercy! You want to keep them "just in case" you eventually need them in the future? Ouch ouch ouch! The infamous "in case I need it." You really, really want to keep them? No problem: Have a backup of your structure file. At worst, create a big "zzzOldUselessThings" method, and copy & paste the code of all those methods, then comment the whole thing out (to make sure the method compiles with no error), and then delete the methods.


Just be careful with methods called in a way that makes them look unused while, in fact, they are used: In the column of QuickReport document, in the formula of a 4D Write document, in a call to EXECUTE FORMULA that dynamically builds the name of the method, etc. For me, I always add a suffix ("_E", if you are curious) to the name of these methods. This suffix means "Careful, the method is used by its hard-coded name". I then know I must avoid deleting (or even renaming) it, unless I've carefully checked that it is really unused.


One last point: The methods declared in a COMPILER_something method (for example, you clicked the "Generate Typing" button in the Compiler window), are never listed as unused. Precisely because they are used in this method, and because COMPILER methods can also be run. But… I'm going to talk about this with the R&D people, just a few seats away from me. Practically speaking, this means that if you are in this situation, you can: (1) Comment the code of the COMPILER_something, (2) Find unused methods. Don't forget to uncomment the COMPILER_something method once you're done. And if you deleted some unused methods, think about deleting the declarations as well.


Cleaning (which means deleting) unused global variables - this time the GFR will find all process and interprocess variables explicitly declared but unused - is also important. Even more so in compiled mode; Even more so in a client/server environment. In compiled mode, 4D builds a "Table of process variables" for every process. This table contains all the process variables the compilation has detected. Yes, you have read it as it must be read, and I really wrote all. Even ones that will never been used in the current running process. By deleting the unused variables, you reduce the time it takes to create a process, to delete a process and to organize memory.


Again a warning: Just like for methods, be cautious with variables eventually used by their hard-coded name in the code.



Now, let's take a minute to focus on a new feature of 4D v13: Searching dependencies of a method.


Search pop-up


This search will find all the called methods and forms, recursively. For example, if you have a DoThis method which calls the DoThat method, which calls AndHop (and DoThis doesn't call AndHop), the "Search Dependencies…" of DoThis will correctly list DoThat and AndHop (yeah, I know. I use silly names in the example. It's my choice.)


Search result


It's very useful for moving code between two 4D applications (each of them opened with a copy of 4D).


While we're talking about this, I'd like to report a slight problem that was detected with version 13.0, which stupidly does not allow you to move objects from the result window to another 4D application. What a pity. The bug has been fixed in 4D v13 Hotfix 1, available if you are a 4D Partner. If you're not, then you have to wait for version 13.1. Apologies for the inconvenience.


There is another super new feature in 4D v13: It is now possible to replace a style sheet in forms. You probably already know that v13 comes with a new style sheet named "Automatic." If you didn't, now you do6. To replace the "Default" style - for example - with the "Automatic" style is now a question of seconds. No need to open each and every form to manually change the properties of objects.


Ok. I'm 100% aware there is always room for more and more features. And I will not fail to talk to the geeks in the R&D department, regardless of the danger of being ridiculed, or worse... If you don't hear from me for more than two months, please inform my family gently of my demise7.



  1. Well, I'm not even sure about this. At this point you still don't know precisely what we'll be talking about.
  2. Yes. This isn't a typo. "Cute". I never saw a cute Web server. But remember we're talking about the people in R&D.
  3. I know the comparison is bold. I'm not even sure it's a comparison, actually.
  5. The frequency may change between two developers. After all, "every 10 years" is probably a development cycle somewhere.
  6. Pardon my English. But writing "know, know now" makes me laugh. Keep in mind that I'm still a kid.
  7. Some day, i'll take a picture of the Death Corridor of R&D. Then you'll understand what i'm talking about.


RSS 0 comment(s) to this post