Re: Cocoa et al as HCI usability problem
Re: Cocoa et al as HCI usability problem
- Subject: Re: Cocoa et al as HCI usability problem
- From: "Michael Ash" <email@hidden>
- Date: Tue, 20 May 2008 10:55:16 +0800
On Tue, May 20, 2008 at 1:33 AM, Peter Duniho <email@hidden> wrote:
>> Date: Mon, 19 May 2008 19:50:57 +0800
>> From: "Michael Ash" <email@hidden>
>>
>> [...] the existence or even the volume of
>> these complains is not evidence of anything other than that this
>> platform actually attracts programmers who aren't using it just
>> because it's hard.
>
> The platform attracts programmers who aren't using it? What does that even
> mean? If the programmers aren't using it, how did the platform attract
> them?
This was apparently badly phrased.
Expanding on it a bit, there are two kinds of platforms:
1) Platforms where all of the developers are there only because they
like a challenge, because developing for the platform is hard, etc.
Example: BrickOS.
2) Platforms where the developers use the platform merely as a tool to
accomplish work.
Platforms of type #1 tend not to get many complaints about the quality
of the documentation, because the environment is expected to be bad,
and the few people who know the platform well enough to write
documentation are expected to spend their time improving the code
instead.
Platforms of type #2 get lots of complaints about the quality of the
documentation because that's what people do.
> In any case, it takes a pretty blind eye to claim that the volume of
> complaints is in no way related to problems.
I disagree. The volume of complaints which we experience is what I
would expect for this community, and therefore I don't think it means
that this community has any special problem.
>>> [...]
>>> Oh, and as an added benefit: because interfaces are treated like types
>>> and
>>> you're not dealing with method signatures directly, there's none of this
>>> "oops, you forgot to include the trailing colon in the selector name"
>>> business (you can probably guess, I've run into that at least once :) ).
>>> The compiler prevents that from happening.
>>
>> If this bothers you that much in ObjC then merely add
>> -Wundeclared-selector to your compiler warning flags.
>
> Never even heard of that flag. Why isn't it the default?
I haven't a clue, I don't and never have worked at Apple or on Xcode.
> This is a decent example of the kinds of usability issues we're talking
> about, and frankly that one looks pretty easy to fix.
On the other hand, at some point while programming on a UNIX system,
you should read the man page for the compiler you're using. Not
defending Apple on this, but you really should do a "man gcc" and read
the thing.
Xcode's default warnings are crap anyway. The first thing I do any
time I create a new project is go to Other Warnings Flags and enter
"-W -Wall -Wno-unused-parameter". Makes life so much easier.
>>> Which is all a long way of saying, the message-sending paradigm in Obj-C
>>> isn't required for the example you give. This is my point. With a
>>> strongly-typed language that includes run-time type information
>>> (something
>>> that's even available in some C++ implementations for that matter), you
>>> don't need to have a whole message-dispatching system for your
>>> function-calling.
>>
>> This makes no sense. If you support this kind of dispatch then you
>> *have* a whole message-dispatching system, no matter what you call it.
>> Java and C# ultimately support the same messaging semantics as ObjC,
>> albeit vastly more verbosely in the more complicated cases, and has
>> similar machinery underneath it making it all happen.
>
> Maybe I'm misinformed about how message-dispatching in Objective-C works.
> But AFAIK, it's nothing like the direct invocation and v-table mechanisms
> that exist in C# and Java. It's the exact opposite of "similar".
Irrelevant implementation details. You can take some kind of
identifier which represents a method name and use that to invoke the
method. In ObjC this is the standard method invocation path, in C# and
Java it may or may not be (I'm given to understand that Java VMs tend
to be implemented using a highly general OO dispatcher which is then
used to implement Java dispatch semantics) but the capability and thus
the mechanism exists.
Others have taken over the discussion on NSUndoManager so I will leave it be.
>> Or even implement something as simple as the Cocoa responder chain,
>> trivial in ObjC, in one of these more "mainstream" languages.
>
> It's trivial in C# too. Most likely, it'd be implemented as a "handleable"
> event, with each responder subscribed to the event, and invocation halted
> after the first subscribed delegate actually handling the event. But it
> wouldn't be hard to do it based on interfaces instead (and in Java, that's
> pretty much the best way to do it, it not having events or delegates), and
> that implementation would look a lot more like Obj-C (in that the invoker
> would simply enumerate the responders until it found the one that implements
> the interface it needs).
I don't see how you can implement the responder chain using
interfaces. The responder chain passes *arbitrary* messages which do
not exist at compile time. You need to be able to take an arbitrary
string, then walk the chain to find an object which implements a
method with that name. From what I understand of interfaces, it would
require all of the possible messages to be defined at compile time.
I'm sure it's possible in C# or Java but it's not going to be as easy.
In your other posts you keep talking about how these are framework
facilities so it doesn't matter how easy it is to implement. This is
rather missing the point. The point is that similar facilities can be
easily constructed by us, the end-programmer. Sure, I'm not going to
be rewriting NSUndoManager or distributed objects, that would be
silly. But I am going to be implementing invocation-capturing object
proxies for my own use, for example to have one object automatically
forward messages to objects it contains, or to wrap a collection
mutating message in a transaction so I can make that modification
thread safe. The fact that these things take only a few lines of easy
code make it a lot more practical to use these techniques on a regular
basis for things which the framework developers *didn't* anticipate in
advance.
>>> Likewise, interfaces aren't something you use _everywhere_ in Java and
>>> C#.
>>> You use them only when you need them. The difference is that in Java
>>> and
>>> C#, the compiler "always" (*) knows whether what you're doing is
>>> reasonable
>>> or not.
>>
>> Even with your caveat, this is insane.
>
> Yes, using words like "absurd" and "insane" to describe the person with whom
> you're discussing the issues is a really mature, productive way to engage
> them.
I'm not describing you as insane, I'm describing your statement as
insane. There's a difference. And stating that "the compiler 'always'
knows whether what you're doing is reasonable or not" *is* insane. Is
this pseudocode reasonable?
function sort(array):
for index in range(array - 1):
if array[index] > array[index + 1]:
swap(array[index], array[index + 1])
No, of course not; this is not a sort, just a broken piece of one. If
you translate this pseudocode into Java or C#, will the compiler tell
you that this code is unreasonable? If your answer is "yes", then I'm
switching right now, because gcc is woefully incapable of DWIM.
>> No compiler can stop you from
>> writing unreasonable code. It may be able to stop you from writing
>> code that treats an object as something it's not, but that is only one
>> tiny corner in an enormous universe of unreasonableness.
>
> You're missing the point. For things that the compiler _can_ do easily, it
> _should_. The lack of true constructors in Obj-C is an example of this.
I understand that, but you're missing the point as well. The compiler
can't do this easily. Or rather, it can, but in doing so it destroys
serious capabilities of the language. You can't just say that the
compiler can easily enforce strict type checking therefore it should.
The question is not only what benefits this brings, but what changes
to the language it causes.
Now, you may think that the capabilities which get destroyed in this
process are pointless, but you need to realize that there are a lot of
us out there who don't think that way.
>> This is, of
>> course, the fundamental point of contention between statically and
>> dynamically typed languages. Us dynamic advocates know that the
>> compiler can detect these things, we just don't care. You treat these
>> bugs like any other bugs, and you catch them in testing. Sure, it's
>> convenient to catch them when you compile instead, but is it worth the
>> enormous loss of flexibility? The people on this side say no. If you
>> disagree, that's fine, but realize that it's a fundamental matter of
>> opinion, not simply that your compilers are able to catch all your
>> errors and ours are not.
>
> Well, I'm still waiting for someone to show me how that flexibility is used.
> You are certainly doing a great job of stating the same party line I've
> heard countless times already. But you're also failing to provide a
> compelling example of how this flexibility comes into play in the real
> world. Again, this is not only typical, it's characteristic of _every_
> single time I've heard the party line stated.
I would have figured that NSUndoManager, which gets used constantly in
Cocoa apps and which has, as far as I know, no equivalent in the Java
or C# world, would be a pretty good example of the flexibility coming
into play in the real world. Of course, it doesn't help when you don't
know what it does or how it works and don't find out.
Anyway, here's a random list of other ways in which the flexibility
can be used in the real world. (They are things that I or my
colleagues have actually done, mind, so they're in no way contrived
examples.) I'm also including a rough estimate of the line count for
implementing each one, since as I mentioned above, the pertinent fact
in this comparison often isn't whether it can be done, but how
difficult it is and thus how practical it is to use this sort of
technique on a regular basis:
- Use message forwarding to simulate multiple inheritance (3 lines)
- Use message forwarding to present an interface which is implemented
by multiple internal objects (5 lines)
- Write a method to enable/disable menu items by calling a method with
a defined signature, such as adding "validate_" to the target message
of the menu item, and using the returned yes/no to enable/disable (3
lines)
- Map a network protocol's commands to object methods by appending a
standard suffix to the end of the command, then invoking the method
with that name (2 lines)
- Proxy messages across to another thread with blocking semantics that
emulate coroutines (10 lines)
Mike
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden