Solipsism Gradient

Rainer Brockerhoff’s blog

Browsing Posts published in March, 2006

Now and then I read complaints about Xcode on blogs and mailing lists. It’s come a long way but some parts are still slow and cumbersome, granted. One of the complaints – which usually comes from Java or Windows C++ migrants – is that Xcode has no refactoring aids. Some people even publish workarounds.

So what is this refactoring thing anyway? According to Wikipedia:

Refactoring is the process of rewriting a computer program or other material to improve its structure or readability, while explicitly keeping its meaning or behavior…

Refactoring does not fix bugs or add new functionality. Rather it is designed to improve the understandability of the code or change its structure and design, and remove dead code, to make it easier for human maintenance in the future. In particular, adding new behavior to a program might be difficult with the program’s given structure, so a developer might refactor it first to make it easy, and then add the new behavior.

I’d tend to agree with that, up to a point. I usually refactor when I reach a dead end in the software’s structure, that is, when the current structure won’t allow me to proceed implementing what I want to implement. Or – probably the same thing, essentially – when I find myself implementing things I don’t want to implement anymore.

But my tendency (see fractal programming) is to do it in the reverse order; I write some code that does new stuff in a new way. Then I migrate lots of old code into the new scheme, often rewriting it radically if necessary, or throwing entire blocks away. (Well, not literally at first; I prefer to comment such blocks out or move them into a “dead code” file for later reference.)

Now, the aforementioned migrants usually don’t see it that way. Rather, they want some automation to make the process easier:

An automated tool such as a SCIDs to help you do might work like this:

– I have a method which has some code that I would like to pull out into its own method.

– I highlight the offending code.

– I select Extract Method from a popup menu

– The RefactoringBrowser asks me to name the method and automatically creates it and inserts the highlighted code.

– In the current method, the highlighted code is replace by an invocation to the newly created method.

All very nice, but it presumes several things which I don’t see coming to Xcode (at least not to the Objective-C parts):

– You have a very regular, structured style of coding that conforms to standards the “RefactoringBrowser” understands.

– You always use the standard refactoring methods, such as expanding, collapsing, pulling out, pushing in, whatever.

– All source code in your project has been previously parsed and stored in the SCID (source code in database), so the browser and refactoring software have a perfect understanding of your code.

This is perfectly possible (or at least I’m told it is) in Java and perhaps in C++ – though I’m skeptical about the latter. I was astounded when a friend, who was qualifying to some Java certificate or other, asked me to have a look at his source code. A quite trivial program was expanded to several dozen source files, consisting of literally hundreds of small methods that differed from each other only by name and a few characters or line. No doubt everything was set up very logically and hierarchically and according to whatever standards a certified Java programmer must obey, but… it was completely illegible by my (admittedly eccentric) standards. It was code only a SCID could love.

So, suppose my friend decided to refactor his code. Just renaming a few classes must necessarily entail profound changes in all source and project files. Not only must the filenames themselves be changed, but all mentions of this class must also be changed. Wait, don’t we have global search & replace for that…?

But, of course, renaming classes or methods is trivial. Maybe it’s suddenly obvious that you need to push some methods off into a subclass, or pull them up into their superclass. Wouldn’t it be nice to have this done automatically?

Well, not really. First off, inheritance is much less used in Objective-C – or at least, I use it less than I used to do in my C++ days (I refuse to learn Java). Runtime binding, introspection and categories mean you usually don’t have to subclass more than one or two deep from the standard Cocoa classes. In fact, I believe I just today went to the third subclass level for the first time. So, automating such a superfluous process makes little sense.

Second, remember that Objective-C is just a small superset of C (unlike Java and C++ which are C-like languages). And that Mac OS X is Unix-based, with many headers pulled in from heterogenous sources. This means, of course, that all the old crufty things of the old C days are still there… pointers, pointer casting, weird #defines, other tricks – you name it. And all of this is liable to be #included into your poor unsuspecting code if you do any work at all with Carbon or BSD APIs, as most non-trivial applications need to.

In other words, I don’t believe it’s possible to feed all of this into a SCID and expect it to behave rationally; of course the gcc compiler has to make sense of all this eventually, but I seriously doubt it could be easily refactored to go back and forth from its internal representation to the source code while it’s being edited. It’s still, essentially, a batch processor.

Suppose someone pulled this transformation off. Suppose all the old C headers were tamed to make them compatible. Suppose we had everything in a hierarchical, intelligent, refactoring browser/editor. Now what?

It may be some congenital deficiency in my own neural wiring, but I can’t recall ever refactoring my code twice the same way (except for that trivial class/method renaming). So again, not much for an automated “RefactoringBrowser” to do.

Well. All this to, finally, say that I’ve been stuck refactoring some of my code – specifically, the XRay II file system browser back-end… and of course, no automation would have helped me. Nor would I have trusted it to do anything like what I want.

This is perhaps the third or fourth version of it, and it’s easily the most complex refactoring I’ve ever done. Unfortunately there are no intermediate steps. 20 days ago everything was compiling and running nicely (except, of course, for the problems that led me to this refactoring attempt). Then suddenly it’s like open-heart surgery. Nothing compiles and the number of error messages is so great that gcc throws its metaphorical hands up and goes off to sulk in a corner. I can’t close the patient up again until everything has been put back into place – even if it’s not the same place. And it’s a lot of information to hold in one’s head at the same time. I suppose I must get a second monitor, but that’s not practical at this moment.

And the availability of powerful time-sinks like the Internet means that it’s almost impossible to summon the necessary concentration to do the surgery in a single run. I’ve made serious progress over this weekend by the simple expedient of staying overnight with some friends who don’t have an Internet connection (or, even, a phone line). Still, sometimes it’s necessary to read and write e-mails, chat, even write long posts about refactoring… icon_wink.gif

Even so, I hope to get past this obstacle during the next few days and write a little about actual results. Turns out I learned a lot about in the process. More as soon as possible, then.

No comments

Posted by rafael:
mano, escolheu o texto perfeito para gastar um tempo e traduzir.

muito obrigado.

Pre-empted.

No comments

I was about to write a long, carefully reasoned post, explaining why Apple should not sell Mac OS X as a separate item for generic Intel boxes…

…when the CodePoet pre-empted me with even better arguments. So please go read “Should Apple sell Mac OS X for beige Boxes?“…

Nando wrote:

Well this wouldn’t work on our actual system I guess, but if you prepared the system to have an ID or other metadata for each icon, I really think it could be done. But all I want for now is to keep my day job icon_biggrin.gif

Well, I sympathize with your last sentence icon_smile.gif.

Still, there’s no way to make an ID for each icon that reliably tells if some custom isual is visually similar to a document icon already on the system. At least with the current state-of-the-art of image recognition software.

Posted by Nando:
Well this wouldn’t work on our actual system I guess, but if you prepared the system to have an ID or other metadata for each icon, I really think it could be done. But all I want for now is to keep my day job icon_biggrin.gif

Nando wrote:

The problem really lies within the file’s data fork, once you change that you can easily have the application open a file that is not attached to it, which might not be a succesful task.

I think you’re misinformed about what’s in the data fork; the contents of that have very little to do with file-application binding. It’s just unstructured data as far as the system is concerned.

Nando wrote:

One thing that could work is have the software check if the icon it’s file holds is not the icon for another application’s file. The system has a list of the icons for each file type, so a background check on that wouldn’t take long at all, probably not over 0.3 seconds…

Unfortunately, that’s impossible. The system would have to locate all the icons from the list (usually thousands), read them (they’re usually from 32K to 64K in size) and compare all pixels with that custom icon; even so, changing one single pixel would cause the comparison to fail. It would take several minutes and be completely unreliable…

Posted by Nando:
I agree with what you’ve said from a security and development point of view, the current methods the system uses to identify the application to which a file is registered seems quite secure to me though. I’ve decided to play with some of my files, changing the extension of a .mov file to .doc, and the system would recognize it as a Quicktime movie just fine. I did that with non-apple formats, and even a document kind I created for fun, and it would open on the right application even if saved with anotehr extension.

The problem really lies within the file’s data fork, once you change that you can easily have the application open a file that is not attached to it, which might not be a succesful task. But in the case of malicious files, the icon is what really makes the confusion, as you have said on a recent post.

Custom icons are easy to apply to files, you can do it easily from Finder itself, with special applications such as IconFactory’s Pixadex or Unsanity’s Shapeshifter. The second one, as far as I know, really does play with the data forks, changing the icons from inside out, while Pixadex just applies them as a cover that is easily removable.

On either case, killing custom icons is really not a solution. First of all because it would mean a dead end to those who, like me, make a living out of that. Ask the guys from IconFactory and MacThemes Forums, they’ll probably like their Macs pretty with custom themes and icons than a “secure” one – and we know this doesn’t actually threatens anyone’s security, yet.

One thing that could work is have the software check if the icon it’s file holds is not the icon for another application’s file. The system has a list of the icons for each file type, so a background check on that wouldn’t take long at all, probably not over 0.3 seconds. If the icon is unknown, the software would ask the system “Is this a themed OS?” (something that would be set on System Preferences against Apple’s will or through Third-Party software), if it is themed, carry on with the loading, if it is not, warn the user of the possible security threat.

As complicated as this solution might sound, I don’t see any other way to keep everyone happy – and secure. So let’s just hope in 5 years the Mac is still as secure as now, it’s probably the best we can do.

Forgot to say this, but the Unsanity folks had previously posted details on a different fake icon method. This uses a “strong binding” resource to change both the icon and the application used to open a document; when the document is a malicious Terminal script, the effect is much the same as hiding an application under a document icon.

In any event, the principle is the same: forcing the Finder to display an icon different from the one ordinarily defined by the normal characteristics of the file. Both methods subvert a useful feature which was implemented with some cost.

Photos licensed by Creative Commons license. Unless otherwise noted, content © 2002-2024 by Rainer Brockerhoff. Iravan child theme by Rainer Brockerhoff, based on Arjuna-X, a WordPress Theme by SRS Solutions. jQuery UI based on Aristo.