TechHui

Hawaiʻi's Technology Community

Building a Native OS X Desktop App: First Impressions

Not content to let Pat and Sherwin have all the fun with Cocoa development, I decided to dive in today. I just finished my first application. Its a simple note organizer for personal use I built to learn about OS X desktop development. Given the fact I'm new to the entire stack including Objective C, Xcode, Interface Builder, the APIs, etc., I think the fact I could get something up and running in a day is testament to the maturity of the APIs and design of the tools.

Coming from a Java Swing, C# WinForms/WPF and Flex background, my first impressions are:
- The Cocoa API's are very nicely designed. The maturity of the system is readily apparent.
- I like the way best practice UI design patterns, such as MVC and the observer pattern, are baked into the tools.
- Interface Builder is perhaps the best WYSIWYG UI builder I've used.
- There are a few design decisions that seem to be arbitrarily inconsistent with every other popular UI toolkit (e.g. putting the view coordinate system's origin in the lower left corner.)
- Objective C is horrible.

To the last point, I don't know why Apple insists on using this dated language, that can best be described as Java's creepy uncle. The awkward syntax, which wreaks of the 1980s, its basically C with a mishmash of smalltalk-like extensions and macro hacks that poorly approximate first order language concepts such as attributes, annotations, delegates, etc., all of which have been elegantly incorporated into modern languages such as Java and C#. I don't understand why Apple always has to do its own thing, especially when clearly superior solutions are freely available. If Apple can't bring itself to use Java or C# for religious reasons, it should consider designing its own modern language. Objective C is simply insufferable to developers used to modern languages. How can anyone look at NSNumber* value = [[NSNumber alloc] initWithFloat:1.0]; and not be a little angry it doesn't read Float value = 1.0?

Enough about the language. The tools and libraries are great. I look forward to learning a bit more about the other libraries tomorrow.


Ikayzo - Design • Build • Localize | Web • Desktop • Mobile

Views: 415

Comment

You need to be a member of TechHui to add comments!

Join TechHui

Comment by Daniel Leuck on October 12, 2009 at 12:50pm
Syntax is a purely subjective thing, some people don't like the Obj-C syntax. Personally I think that it is head and tails above the likes of C#, Java, Ruby etc which try to make things concise but end up just making code less readable.
Hmmm... This sounds more like a criticism of Perl. Have you spent much time with Java or C#? One of Java's overarching design goals is readability over all else. Everything is clearly spelled out, with abbreviations being strongly discouraged (far more than in Objective C.) I think you would be hard pressed to find counterexamples. The only exception perhaps being boxing/unboxing.

Its true that syntax is somewhat subjective, but as indicated above, sometimes its pretty clear that a language's syntax is due for an upgrade.
Comment by Martin Pilkington on October 12, 2009 at 12:40pm
I'll give you the NSNumber. I've filed a feature request in Apple's issue tracker asking for easy creation of NSNumber objects by doing something like @1.0, similar to how an NSString can be created with @"foo". That said, you can use [NSNumber numberWithFloat:1.0] to simplify it (technically you don't need the .0 either).

Syntax is a purely subjective thing, some people don't like the Obj-C syntax. Personally I think that it is head and tails above the likes of C#, Java, Ruby etc which try to make things concise but end up just making code less readable due to that and so requiring you to write more comments and reference the documentation more, some people don't mind that.

As for the init method, it's another case of Obj-C's philosophy that the language should only have features that cannot be done in APIs. -init is just a method like any other, there's no need to add special classes of methods for creating objects.
Comment by Daniel Leuck on October 12, 2009 at 12:31pm
BTW - I hope you know that, while I do think its an issue with the platform, I am also just giving you a hard time. I'm happy to buy you both beers next time you are in town. If I have enough, I might start to think Object C is pretty. :-)
Comment by Daniel Leuck on October 12, 2009 at 12:21pm
C'mon guys. The runtime has some nice features, but I don't think either of you can look me in the eyes and say Objective C has anything close to the terse, clear syntax people expect from modern languages.

Creating a Float object in Java:
Float value = 1.0f;

Creating a Float object in C#:
Single value = 1.0F;

Creating a float object in Objective C:
NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];

Initializing some instance variables in a Java constructor:
public MyClass() {
firsName="Joe";
lastName="Smith";
}

Initializing some instance variables in an Objective C initializer:

- (id) init {
if ( self = [super init] ) {
[self setFirstName:@"Joe"];
[self setLastName:@"Smith"];
}
return self;
}

It isn't just ugly. Its eyebrows are connected. I understand it has a good personality, but...
Comment by Stuart Malin on October 12, 2009 at 12:42am
Martin said:
Now, as for why Apple doesn't use Java or C# beyond Obj-C's dynamic nature, partly because many of the APIs in Cocoa are older than C# or Java and that there's no major benefit to rewriting all that code

Not only the Cocoa code, but that there's a huge amount of Core Foundation code underlying the OS, to which an app is linked. The code base must be HUGeE, and a rewrite would put forward motion on hold. Apple has instead moved forward.


Dan said:
I cringe every time I instantiate an object: MyClass *object = [[MyClass alloc] init]; Eck!

Cringe. C'mon... just do it (lol). Actually, now that I deeply understand what is going on in that two part call, it is my friend. Not all of my object instantaitions are so plain vanilla. Actually, nowadays very few are. Sometimes I invoke class factory methods to get autreleased objects, oftentimes the -init call is -initWithParamaters, and sometimes when it is plain vanilla, the two part construction reminds me about my need for memory management. I, by the way, am no fan of garbage collection, but rather am a disciplined retain-releasor. I can envision all too many ways that by not paying attention, it is all too easy to create reference loops among objects that prevent garbage collection from working. Sure, reference "cycles" (in a directed graph sense) are as easily possible in manual memory management, but for me the needed attention to memory management keeps me en-guard.

Martin said:
The two part initialisation...

More correctly, the two parts are allocation and initialization, quite distinct. I know you know that :-)


Thanks for the reference to Matt Gallagher's post!
Comment by Martin Pilkington on October 11, 2009 at 11:59pm
This capability exists in many JVM and CLR languages including BeanShell (basically optionally typed Java), which was developed by Pat and to which I contributed. If you need this in a Java or .NET environment you simply use a language that supports it, and the tools (Eclipse and VisualStudio) provide excellent support for these languages side by side with Java and C#. Additionally, there are many excellent AOP libraries that provide the ability to intercept and route method calls.

These runtimes do have some degree of support for more dynamic languages, but the languages of Java and C# don't take full advantage of this. If they did then I wouldn't ever get a compiler error when I call a method on a class that doesn't implement it. Now Objective-C's runtime does allow other languages to be built on top of it. The MacRuby project is building a version of Ruby on top of the runtime, which means it gets round the performance problem of bridges.

Unless things have changed very recently, I don't believe Java and C# support features such as method swizzling, where you can change the method implementation of an object with another method at runtime (this can be any object in the system). Conveniently there was a good post today about this very issue of why Obj-C is still used: http://cocoawithlove.com/2009/10/objective-c-niche-why-it-survives-in.html

For the aforementioned reasons, I respectfully disagree. I'm happy to learn a new language. My issues are specifically with Objective C. Today I reviewed the language specification, and it just looks...well...old, and not particularly elegant or expressive by modern standards. I cringe every time I instantiate an object: MyClass *object = [[MyClass alloc] init]; Eck!

The two part initialisation is due partly to the fact that Obj-C was (until 2007) manual memory managed. This splits up the allocation of memory and creation of the object from the initialisation of the default state of the object. If you are just using alloc] init] then you can replace it with +new, but any other initialisation requires you to use two part initialisation. Another part of this is that classes in Objective-C are actually objects themselves. Unlike other languages where classes are special distinct types from objects, where a constructor is needed, you can send messages to any class.

I can understand this, especially given Apple's general philosophy. I just wish they would start anew or at least use a more recent starting point. Apple could join the JCP and contribute to Java's evolution. Its not hard. We did it. Also note that C# is an ECMA standard. Apple could also do something new, as they did with AppleScript.

If Apple was to use a more recent starting point then it likely would forego both Java and C# and use a language that is a much better fit for Cocoa such as Ruby or Python, but as these are scripting languages it makes it a bit harder to manage, especially performance wise. It is simply a case of what Apple uses every day to make Cocoa do what it does aren't the core fundamental features of Java and C# like they are in Objective-C. There's nothing you can't do in any language as they're all Turing Complete, but Obj-C bakes this stuff into the core of the language, making it much easier to harness
Comment by Daniel Leuck on October 11, 2009 at 5:45pm
Martin Pilkington: You have all the introspection tools to test before hand, but if you don't then there are methods like forwarding and dynamic method creation that allow you to handle unimplemented methods before finally resorting to an exception.
This capability exists in many JVM and CLR languages including BeanShell (basically optionally typed Java), which was developed by Pat and to which I contributed. If you need this in a Java or .NET environment you simply use a language that supports it, and the tools (Eclipse and VisualStudio) provide excellent support for these languages side by side with Java and C#. Additionally, there are many excellent AOP libraries that provide the ability to intercept and route method calls.
Martin Pilkington: As for the methods, they aren't named parameters but interspersed parameters, something that in believe only Obj-C and Smalltalk do. I wrote an article on them and why they are different to named parameters.
I stand corrected. Your post makes the distinction clear.
Martin Pilkington: Now, as for why Apple doesn't use Java or C# beyond Obj-C's dynamic nature, partly because many of the APIs in Cocoa are older than C# or Java...
I'm sure this is the reason. Its whats already there, and people are accustom to it.
Martin Pilkington: ...and that there's no major benefit to rewriting all that code in them beyond meaning people don't have to learn a new language.
For the aforementioned reasons, I respectfully disagree. I'm happy to learn a new language. My issues are specifically with Objective C. Today I reviewed the language specification, and it just looks...well...old, and not particularly elegant or expressive by modern standards. I cringe every time I instantiate an object: MyClass *object = [[MyClass alloc] init]; Eck!
Martin Pilkington: It also means Apple has control over where the language goes. Try telling MS to use a language someone else has the keys to.
I can understand this, especially given Apple's general philosophy. I just wish they would start anew or at least use a more recent starting point. Apple could join the JCP and contribute to Java's evolution. Its not hard. We did it. Also note that C# is an ECMA standard. Apple could also do something new, as they did with AppleScript.
Stuart Malin: Can you then send myButton a message and tell it, at runtime, to change the method it invokes? Can you send the button a message and tell it which object it should send its message to?
Yes. It would be trivial for me to enable any of these capabilities in the SDL/Swing framework because there are multiple points at which I can intercept the calls. Both the Java and .NET platforms have the ability to do introspection and dynamically generate bytecode (IL in .NET parlance) at runtime. I've worked on frameworks, compilers and interpreters (mostly for DSLs) on both platforms, and have rarely found my self saying, "I want to enable capability X, but its impossible on this platform."
Comment by Stuart Malin on October 11, 2009 at 3:22pm
button ID="myButton" do="myCoolMethod"< ...which would invoke a Java method in the controller called myCoolMethod().

Can you then send myButton a message and tell it, at runtime, to change the method it invokes? Can you send the button a message and tell it which object it should send its message to? Can you observe properties of the button and have your code take action when the properties change without adding any code whatsover to the button? Can you then do any of these things for any object? In Cocoa you can, all because of inheritance from NSObject... but then... that's not Objective-C, or is it? (because I believe that NSObject implements some of these things by ISA-swizzling, which, I believe, is a capability consequence of Objective-C. So, again I make the point that there are many sophisticated capabilities in Cocoa programming that the casual or novitiate programmer will have no idea of, that the experienced Cocoa programmer will rely on, and that such features arise from a blurry space between Objective-C and NSObject.
Comment by Stuart Malin on October 11, 2009 at 3:13pm
BTW: I do a lot of my UI in code. Not that I don't like IB, but one can get wickedly optimized by rendering Cells rather than building Views. I have in my present app and NSTableView for which I manage all the table cell rendering, and use only two cells to render a table regardless of size, one of those cells backed by an NSView which I make live to handle the user interaction in the row that is active. In this regard, much of my app's GUI is actually a chimera, it is all painted pixels, except the area where the mouse is, under which I activate a live view. NSView (and all subclaases derived therefrom) are "expensive" objects whereas NSCell is meant to be lightweight. However, it took me painstaking repeated failed approaches to learn how to do this. But is worth it. As a consequence, my app has a very small memory footprint and is very very responsive at the GUI. Now, all this can coolness can only be laid at the doorstep of Cocoa, not Objective-C....

And so one of my acute observations is that while Objective-C exists "down there" at some low level, it in some way shapes the Cocoa model. Cocoa is extensively coupled with Objective-C, although to what degree I don't know (that is, could Cocoa be ported to another language? Probably).

And interesting case study is The Cocotron, which is a port of Cocoa to the Windows platform -- an amazing piece of work. For whatever reason, the creator of The Cocotron retained Objective-C (and wrote an Objective-C for Windows; the code is open source MIT license, btw). My point being that there must be some tightness between Cocoa and Objective-C, and that Cocoa coders rely on Objective-C runtime.

Another interesting thing about Objective-C is Apple's now apparent move away from gcc to LLVM/Clang. This portends some very interesting possibilities for Objective-C, such as the Snow Leopard inclusion of Grand Central Dispatch for enabling C closures.

Ahh -- C. As I "c" it, as I said earlier, C is not baggage to me, but a world of libraries that are accessible and incorporatable. From javascript and ruby interpreters to the TokyoCabinet datastore, and even being an Erlang node, the world is open to my Cocoa app. Can you embed any of these in a Java app?

Back to coding...
Comment by Martin Pilkington on October 11, 2009 at 2:06pm
Actually, it isn't a case of send and hope for the best. You have all the introspection tools to test before hand, but if you don't then there are methods like forwarding and dynamic method creation that allow you to handle unimplemented methods before finally resorting to an exception. Now there isn't any way for static analysis to help you beyond placing assumptions ino your code. If you makethem more than assumptions you take away some dynamism, this is why dynamic and static languages are either end of the spectrum.

As for the methods, they aren't named parameters but interspersed parameters, something that in believe only Obj-C and Smalltalk do. I wrote an article on them and why they are different to named
parameters on my blog: http://www.mcubedsw.com/blog/index.php/site/comments/the_named_argument/

Now, as for why Apple doesn't use Java or C# beyond Obj-C's dynamic nature, partly because many of the APIs in Cocoa are older than C# or Java and that there's no major benefit to rewriting all that code in them beyond meaning people don't have to learn a new language. It also means Apple has control over where the language goes. Try telling MS to use a language someone else has the keys to

Sponsors

web design, web development, localization

© 2024   Created by Daniel Leuck.   Powered by

Badges  |  Report an Issue  |  Terms of Service