[Pyobjc-dev] Re: [Pythonmac-SIG] pyobjc / cocoa
Ted Horst
Ted.Horst@ubsw.com
Thu, 17 Oct 2002 11:06:48 -0500
(I sent this to pyobjc-dev@lists.sourceforge.net yesterday, cross-posting
now to include everybody involved in the debate.
Just a little background on my experience; I have been an Objective-C
developer (on NeXTStep) for almost 10 years and a python user since 1.2. I
wrote my own version of a python-Objective-C bridge (there were 3 or 4
different versions originally) and made some small contributions to the
unified PyObjC project which was brought together by Lele Gaifax around
1996. My version started as a very thin wrapper around objc_msgSendv which
I then wrapped with a python class to get method call syntax. Since then I
have used the unfied version of PyObjC (which bbum contributed heavily to)
almost every day to interact with our large, fairly complex interest rate
derivatives trading system. It has been am absolute joy to use and has
allowed me to do things that I just would not have done without it. I am
currently struggling to figure out how to get anything remotely resembling
this kind of environment in the C++ system I am currently working on. Its
quite depressing, actually.)
Anyway here is the original message:
I apologize for low content ratio of this post, but as a once and
(hopefully) future heavy user of the pyobjc bridge, I just wanted to
whole-heartedly agree with everything that Bill says in this post. Explicit
and straightforward are the way to go.
Now that I've delurked temporarily, I also want to take this opportunity to
extend a huge thanks to Ronald and Bill for their work on this project. I
am really looking forward to getting back to this kind of environment.
On Wed, 16 Oct 2002, bbum@mac.com wrote:
> (Jack; thanks for the CC to pyobjc. I have now subscribed to
> pythonmac and will try to keep up with things in this SIG.)
>
> First, a brief update on the progress made on the PyObjC project.
>
> The module itself is now compatible with the Apple supplied build of
> Python 2.2.
>
> At this point, the developer can create a new project in Project
> Builder, select "Cocoa-Python Application" (a custom template included
> with PyObjC), and Project Builder will create a new Cocoa application
> project that is implemented entirely in Python. The project template
> includes an implementation for a basic application delegate (NSObject
> subclass) that includes target/actions, outlets, and notification
> handling.
>
> When the 'install' target is used, the resulting application runs
> completely standalone on any OS X 10.2 machine without requiring that
> the user has preinstalled PyObjC or a custom build of Python.
>
> In comparison to Cocoa-Java, the PyObjC bridge is significantly less
> intrusive. More on this below.
>
> In comparison to Cocoa-AppleScript (AppleScript Studio), the PyObjC
> bridge presents a development experience that is much closer to pure
> Cocoa. AppleScript Studio is really a mix of Cocoa widgets into
> AppleScript style event handling-- the end result is very powerful, but
> it isn't Cooca programming.
>
> At this point, the PyObjC bridge is being used in several production
> quality projects/products. I.e. it is working now and working
> extremely well!!
>
> (And, again, a huge note of thanks to Ronald -- his work on the
> subclassing and method dispatch mechanisms made it all possible.)
>
> More information interspersed with Jack's and Ronald's text below.
>
> On Wednesday, October 16, 2002, at 09:17 AM, Jack Jansen wrote:
> > [I've added pyobjc-dev to the distribution]
> > On Wednesday, October 16, 2002, at 02:28 , Ronald Oussoren wrote:
> >>> Something that is open to discussion, I think, is how to map ObjC
> >>> names to Python names. The current PyObjC code supports two
> >>> compile-time options, object.message_withFoo_(arg1, arg2) and
> >>> another that I forget with even more underscores in there (this
> >>> mapping is ambiguous: it maps to both [object message: withFoo:] and
> >>> to [object message_withFoo:]). The Java-ObjC brigde has simply
> >>> defined sensible static mappings for all names used in Cocoa, and
> >>> the above would probably become something like
> >>> object.messagewithFoo() or object.messageWithFoo(). Python's current
> >>> method is more flexible, but boy does it lead to ugly method names
> >>> in your code...
> >>
> >> Changing the mapping from Objective-C names to/from Python names is
> >> definitely open for discusion.
> >>
> >> BTW. The current PyObjC no longer supports object.message__withFoo__.
>
> We have been down this path a number of times over the six year history
> of the PyObjC module. In all cases, we have ended up back with the
> naming conventions that we have now for a number of reasons. Moving
> from double underbar to single underbar was definitely a win -- made
> the code easier to read and write.
>
> > I think that what I would like is one static scheme that is the same
> > (or almost the same) as the Java/ObjC naming scheme, plus a fallback
> > scheme (which could be the current message_withFoo_ scheme). There may
> > be a problem here with overloading, though: if I look at AppKitJava
> > there's often multiple ObjC selectors that map to one Java method
> > name, I'm not sure how they handle this, especially in the face of
> > overriding ObjC methods from Java.
>
> The key value in the PyObjC module is that it provides an ObjC
> development experience that is about as close to transparent as can be
> achieved when mapping from one language to another. One of the most
> frustrating aspects of doing ObjC/Java (the bridge existed back to
> WebObjects 3.0 in 1997) was because of the mapping of method names.
> Specifically, the developer effectively had to learn three APIs deeply
> to be effective -- the ObjC API, the Java SDK APIs, and this weird
> permutation of the ObjC APIs as presented in Java.
>
> End result; the developer is constantly frustrated by constantly
> having to do the mapping in their heads. Worse, the mapped
> representation -- the conversion from, say, setObject:forKey: to
> setObjectForKey() -- loses the emphasis on the number and order of
> parameters that is emphasized by ObjC's method naming scheme.
>
> From personal experience-- both as a developer and a WebObjects
> training instructor-- I can confidently say that all of the effort that
> was put into presenting the ObjC API in Java such that it appeared to
> be a Java API caused a hell of a lot more confusion than it ever
> perpetuated clarity!
>
> Even if it slightly less Python-Pretty, this...
>
> mutableDictionary.setObject_forKey_ ( "foo", "bar" )
>
> ... is ultimately easier to read and maintain than this...
>
> mutableDictionary.setObjectForKey( "foo", "bar" )
>
> ... for a number of reasons:
>
> - the first is immediately recognizable as an ObjC method call.
> Regardless of how transparent the bridge is, the bridge is there and it
> does affect behavior. Trying to hide it makes maintenance
> significantly more expensive and the introduction of new developers
> into a project harder. (I helped maintain a mixed ObjC<->Java codebase
> with 500,000+ lines of code for over 3 years. The bridge was the
> single largest cause of problems in the project -- that it tried to
> hide the "crossing of the bridge" just confused things.)
>
> - the first form preserves the argumentation information as
> provided by the traditional ObjC method name (setObject:forKey:)-- the
> developer can easily map between that syntax and the original ObjC
> method. The second loses that information and the developer can easily
> assume that the key should be first. This is a huge problem among my
> development team with WebObjects 5.x -- all of us make this kind of
> mistake on a regular basis.
>
> - the first has the distinct advantage of allowing the developer to
> *always* be able to deduce the original ObjC method name by simply
> looking at the code. The developer doesn't have to go follow some
> random mapping to try and figure out what the ObjC method's name
> originally was.
>
> > Hmm, even if that isn't possible we could cop out: if the method name
> > translation routine finds that a certain name isn't in the
> > dictionaries it would simply add it. Or (more cumbersome, but safer)
> > there could be a (Python) API MapObjCSelector('message:withFoo',
> > 'messageWithFoo') which could then also check that this mapping
> > doesn't conflict with another one. With such a scheme the Python
> > programmer would have to declare any new ObjC messages it uses, but
> > the question is how often this will happen.
>
> Anything that adds more steps to the bridging process is bad. One of
> the most powerful and valuable aspects of the PyObjC bridge is that it
> so totally transparent; much more so than CamlBones (doesn't do
> subclassing), Java<->ObJC (changes the API) and AppleScript<->ObjC (not
> intended to be transparent at all).
>
> The developer is going to be defining new ObjC methods quite often.
> The current PyObjC module can complete replace ObjC within a Cocoa
> project. That is, Python is used to create all of the custom classes
> that one would normally find in a Cocoa project. As such, the
> developer is writing lots of custom methods that implement the
> functionality specific to their application. Certainly, there are
> many cases where the developer is simply overriding existing Cocoa
> providing functionality.
>
> As it is, many of those methods have to be declared such that the
> bridge can figure out how to do the dispatch. Very unfortunate, in
> and of itself, but livable. It would be even more unfortunate if
> every single action method and other custom methods had to be declared,
> as well!
>
> b.bum
>
Visit our website at http://www.ubswarburg.com
This message contains confidential information and is intended only
for the individual named. If you are not the named addressee you
should not disseminate, distribute or copy this e-mail. Please
notify the sender immediately by e-mail if you have received this
e-mail by mistake and delete this e-mail from your system.
E-mail transmission cannot be guaranteed to be secure or error-free
as information could be intercepted, corrupted, lost, destroyed,
arrive late or incomplete, or contain viruses. The sender therefore
does not accept liability for any errors or omissions in the contents
of this message which arise as a result of e-mail transmission. If
verification is required please request a hard-copy version. This
message is provided for informational purposes and should not be
construed as a solicitation or offer to buy or sell any securities or
related financial instruments.