Re: Java vs. Objective-C for Cocoa
Re: Java vs. Objective-C for Cocoa
- Subject: Re: Java vs. Objective-C for Cocoa
- From: Keith Ray <email@hidden>
- Date: Sat, 23 Apr 2005 20:08:18 -0700
NIB files are an impediment to refactorings where a class or method
are referenced by name... for example, my code stopped working when I
did the simple "rename" refactoring (of a member variable) and didn't
update the NIB file to use the new name. Most Smalltalk environments
don't have this problem because they don't use a separate environment
for editing GUIs -- the code and GUI information are all "live"
objects in the same memory "image" rather than source files and nib
files on disk. In Squeak for example, which started out as Apple's
port of Smalltalk-80, there are probably still some objects alive in
its image that were created before 1980... they get saved to disk now
and then, but they are not recreated from source code everytime the
environment is run.
Most refactoring tools in Java, Smalltalk, etc., operate not on source
text as text, but operate on the same semantic information that a
compiler operates on... the refactoring tool can distinguish between a
method named "foo" and a variable named "foo" and a class named "foo"
and will completely ignore comments containing the text "foo". Some of
the smarter tools will look for strings containing "foo".
However, just because some classes might be referenced via strings in
NIB files doesn't mean the refactoring tools for objective-C (and C++)
would be useless... there are lots of classes that are not directly
referenced by NIB files that we work on every day.
Joshua Kerievsky was demonstrating as SD-Expo West some of the
refactorings to patterns in his book
<http://www.industriallogic.com/xp/refactoring/> using the Java IDE
"IDEA" (or maybe he was using Eclipse). It's amazingly productive to
be able to use a few menu items to do the work that would take 5 times
longer to do manually (and be more error-prone). He rewrote his book
before publication to take advantage of the refactorings available in
those IDEs, often shortening the lists of refactorings needed for the
transform-to-design pattern chapters.
The automated refactoring tools for "Extract Method", where you select
some code in a long method and get it extracted into its own method,
will examine variable lifetimes and pass local variables into the new
method (creating the appropriate parameter list and return values).
I'd love to have that tool for legacy C/C++/Objective-C code.
http://www.jetbrains.com/idea/features/refactoring.html
http://www.refactoring.com/tools.html
For example, I'd like to be to do extract methods for just about each
each block of lines starting with a comment in the following
open-source code...
// modified from http://openrj.org/
//
-(int) processFieldMarkers: (char * const) py charSize: (size_t *)
numChars numLines: (size_t *) numLines numFields: (size_t *) numFields
numRecords: (size_t *) numRecords error: (ORJError *) error
{
/* We need to iterate through this, counting the %%'s */
char const *end = py + *numChars;
char const *begin;
char const *start;
char *dest;
char last_char = 0;
int numLinesToInsert;
int numInitialWsToSkip = 0;
int line = 0;
int column = 0;
int leadingCommentChars = 0;
int isInContinuation = 0;
int isInCommentLine = 0;
int fieldLength = 0;
int numFieldsThisRecord = 0;
openrj_assert(NULL != numChars);
openrj_assert(NULL != numFields);
openrj_assert(NULL != numRecords);
openrj_assert(NULL != error);
*numLines = 0;
*numFields = 0;
*numRecords = 0;
/* Remove all carriage returns. This has to be done on other platforms,
* since we might be using data files created on Windows.
*/
for(begin = py, next = py; begin != end; ++begin)
{
if('\r' == *begin)
{
--*numChars;
}
else
{
if(next != begin)
{
*next = *begin;
}
++next;
}
}
end = py + *numChars;
/* Trim all trailing whitespace (space or tab)
*
* This is effected by a single pass through the data, and noting the ends
* of lines and continuation characters
*
*/
for(numLinesToInsert = 0, begin = py, start = py, dest = py; begin
!= end; ++begin)
{
const char this_char = *begin;
size_t cch;
/* In this loop, the variable tasks are as follows:
*
* begin - the current pointer in the processing
* dest - the output pointer
* start - the start of the good input
*/
switch(this_char)
{
case '\n':
/* (1) Copy all from [start:begin) => dest, and advance dest */
cch = (size_t)(begin - start);
dest = copy_advance(dest, start, cch);
/* (2) One more line to insert */
++numLinesToInsert;
/* (3) process the line */
if('\\' == last_char)
{
/* For continuation, just drop dest back one */
--dest;
isInContinuation = 1;
fieldLength += column;
}
else
....
Do Extract Method on the lines following "/* (1) Copy all from ..."
and get the new method, where the only typing you do is the new method
name...
- (void) copyAllBeginningAt: (const char*) begin startingAt: (const
char*) start destination: (char *) dest
{
size_t cch = (size_t)(begin - start);
dest = copy_advance(dest, start, cch);
}
--
C. Keith Ray
<http://homepage.mac.com/keithray/blog/index.html>
<http://homepage.mac.com/keithray/xpminifaq.html>
<http://homepage.mac.com/keithray/resume2.html>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden