Safari on Windows, How do you feel about that? 1
As a matter of fact, I am writing this article in Safari on my Windows laptop right now. It’s a beta application, which you can download from Apple any time you want. Apple has its sites on expanding the browser war a bit, and leveraging the good will from iTunes to get people to switch to Safari. That’s an interesting move. In Steve Job’s Keynote introducing Safari on Windows (about an hour into the video if you want to skip ahead of the OS X Leopard announcements) they replace Firefox and “Other” browsers’ market share instead of encroaching on IE’s market share. My opinion? That 2% not using either IE or Firefox will likely continue using what they are using, particularly if this Opera fanboy is any indication. I also doubt they will put a serious dent in Firefox’s share.
There’s some impressive numbers thrown around by the benchmarks, but benchmarks only show a part of the picture. More than one person is very skeptical about the whole proposition. But is Safari all that bad? Sure it has it’s rough edges, and its a beta, but are these just haters speaking? You know me, I’m not satisfied until I get my hands dirty and form my own opinion. I believe there are some features not fully funished yet, and things can only get better.
The Good
Safari is not the complete loser that some people make it out to be. First, the text rendering is better than either IE or Firefox on my laptop. Firefox needs the most improvement in this area, although it is better than it used to be. The tabs work pretty well, although moving them around is really not that important to me. The user interface is pretty clean, and the RSS feed and bookmark features are pretty nice. If you are familiar with Firefox, you’ll be familiar enough with them. Big text areas like the one I type into to write this article has a little handle on it so I can resize it the way I like. That comes out of the box without any issues whatsoever. Many sites render better in Safari than in either IE or Firefox. It’s like there is some magic voodoo done on the images (maybe like gamma correction done properly) where they seem to look a bit better. There’s a few very subtle things throughout Safari that are nice, but difficult to talk about. Have fun playing around with them.
Now, if you really want to bowl me over with an Apple unique browsing experience, give me that page flipping thing you do with your finder in Safari. That would be really cool! Sometimes when I’m browsing along with several tabs open because I saw something that caught my eye but I want to get back to it, I have a number of tabs open. The little bit of text in the tab title doesn’t always give me an idea of what’s on that tab (and many times that’s the fault of the web designers not giving a decent and succinct title in the page header). I looked, after all this is an Apple product and they have it in iTunes for movies and TV shows. Why not here? Note to Firefox: if you want to add a killer feature give me a way I can quickly go through the things I have open in my tabs. Opera has the thumbnail view, Apple may take my idea (or come to the same conclusion themselves), so this is where you can do something cool.
The Bad
There are some definite quirks. First, despite the hype over the speed, I haven’t seen any real improvement over many of the pages I frequent. My blog takes longer to render than Firefox, and some things just don’t work. For example, I can’t upload files to Typo with Safari. Typo uses AJAX to give me a progress bar, and Safari gets one refresh and stops sending the file. Also, the WYSIWYG editor in Wikispaces doesn’t work in Safari. It’s a problem because I use Wikispaces at work. I’m sure they’ll fix this. I mean if they are serious about taking market share from either Firefox or IE. Another major issue? My OpenID has a feature to install a certificate on your browser for authentication purposes. Unfortunately it does not work with Safari because Safari does not send a certificate request, or a properly formatted one. Again, if you claim to be standards compliant, you have to be completely standards compliant.
There is a feature in the “Edit” menu under “Spelling” to check spelling while typing. Well, its not working and not selectable. I can type something obliviously wrong and it won’t be flagged or corrected. Firefox takes care of this really easily and nicely. I’m sure there are other features that are not working, but I’m probably not going to look into and find them all.
I don’t know what happened yesterday, but Safari became unstable. It just started churning away, eating up all my processing power as it tried to load even the simplest pages. It would churn along for about a minute or so and then render the page—very slowly. I uninstalled and reinstalled Safari and it is working now. That’s OK for a beta, but don’t let it happen in the final release.
The Ugly
I’m not a fan of the blue progress bar behind the location text. It took a few pages before I realized what was going on. I find it distracting, but not a deal breaker. It’s just how they chose to show how things are moving along. I’m also not a fan of the non-standard RSS badge in the location bar. IE, Firefox, Feedburner, and almost every RSS generating source uses the orange feed symbol because it is a standard . Again, if you are going to support standards, please do so. Also, if you are going to differentiate yourselves do it on something that matters and not something like this.
The bookmark handling is fairly nice… when it works properly. The link dragging is still a bit too quirky. I had difficulty dragging links into a folder. All that would happen is the bookmarks would rearrange themselves, which is not what I wanted. Please, take a lesson from Firefox on how to do this properly. I mean, if you are serious about taking marketshare from them you have to be better, not worse.
Tabs in Safari are OK when you have a mouse, but they are a pain when you don’t want to aggravate carpal tunnel syndrom (I don’t have it, but mousing around is a pain) then follow Firefox’s lead with the key combination shortcuts. Ctrl-Tab should move from you to the tab to the right (and wrap around when you are at the end), and Ctrl-Shift-Tab should move you to the tab to the left. In Safari they just move you further down the page. That’s what the Page Up and Page Down keys are for.
The location bar has autocompletion help for you, but I’m curious what selection criteria they use. I started typing the URL for Technorati and the first option was Them Anime Reviews and I haven’t been there in this browser. I typed in the URL for BH Photo Video and one of the first options (before I actually went to BH) was Bleach Portal . I’ll admit I do visit all of these sites on occasion, but it makes me wonder what kind of fanboys are working on Safari :)
The Verdict?
For now I’m going to stick with Firefox as my main browser, but I’ll continue to keep my eye on Safari. Despite its quirks, it has some big advantages over IE, but it doesn’t match Firefox at the moment. I won’t talk about Opera because I don’t have it, and people who are willing to pay for a browser are going to be really happy with what they bought. I think that it is really telling that among the Mac visitors I get, most of them use Firefox. I can only guess that they use it because it is better for them than Safari.
Please, Safari developers, fix the spell checking, the tab quirkiness, the outright malfunctioning things, and give me page flipping. That would rock.
Judicious Use of Closures 9
After going back and reviewing some of my old articles, I got to thinking that my role based authorization system I outlined in this article still reflected my Java bias. I know some people approach new toys and technologies by diving in head first, and then backing off later. I personally try to think of what problems that approach can practically solve. As a result I may be a late bloomer, but the flowers are nicer.
The whole issue of why I thought it could be better is because it is still too Java/C++ based. I tried to make it more rubyesque but I stopped short. You see, in the Java/C++/C# world you think about having to query an object and then do something. This is in stark contrast to the Smalltalk and Ruby approach where you tell an object to do something for you. You can even pass in some extra steps so that you can be very happy. So what’s the difference, and does it really make a big deal? The difference is subtle, but so is elegance. Let’s consider the code I had you write to do work if a user had a particular role:
if @user.is_in_role? (:Admin) Article.find(params[:id]).destroy flash[:notice] = 'Article was successfully deleted.' end
The “is_in_role?” message is straight from Java’s HttpServletRequest interface. It does make sense from a certain point of view, but the control is inverted from what it should be. In short, we should tell the user to do something if they have a roll. Here’s how the same logic should look from the subtle shift in viewpoint:
@user.with_role :Admin do Article.find(params[:id]).destroy flash[:notice] = 'Article was successfully deleted.' end
So what’s the big deal? They both do the same thing, and they are both pretty readable. The big fat hairy deal is in perspective. The first version is interrogative, we are treating the user object like a little child and taking back control. We aren’t letting the user object do his part of the chores. The the second version is imperative, we are telling the user object what we need him to do. We trust him to make judgments like whether he can do it or not. The implementation of the method is just about the same under the covers, but the important thing to stress is who is doing what. We should provide general directions, and the objects should pull their own weight to make it happen.
Ruby is really great when it comes to closures. Every method implicitly handle closures. The trick is the yield keyword. If you want to pass a parameter to the closure, just add it on to the yield command. Here is how our implementation would look if we did the more rubyesque approach:
def with_role role
if roles.include? Role[role]
yield
end
end
That’s pretty slick when you think about it. You can make any method handle closures just by using the yield command. If we needed to pass parameters, we just tack them on after the yield command. There’s tons of applications for it, but it’s best to start off slow. After you add support for a closure to an object’s method, ask yourself if it makes life better. Is the code that matters more readable? Does it simplify life? The answers to those questions will help you walk the balance between elegant and gimmicky.
Contrast Ruby With Java
I’m cheating a little bit with referencing the current specification proposal for JSR for Closures in Java as it represents the closest thing to what you can expect here. First of all, if you use Ruby or Smalltalk you will be sorely disappointed. In a sense, Java closures still follow the same pattern in that the closure is an object—only you have to be explicit about it. Edit: Apparently I missed a very important, and good part of the new Java closure spec. I’m changing the code examples to reflect the preferred method.
First, let’s look at the Java way of solving the problem we solved with Ruby:
if ( user.isInRole("Admin") ) {
Article.find(id).destroy();
sendMessage( "Article was successfully deleted." );
}
It’s fairly readable, and it doesn’t look too bad. Again, we are treating the user object like a little child. We are asking the object about itself and assuming control. The approach has its roots in the procedural world that the C based languages came from. Now let’s look at what the new Java Closures will look like, and whether that will help things be more readable.
user.withRole("Admin") {
Article.find(id).destroy();
sendMessage( "Article was successfully deleted." );
}
There is an uglier way of declaring the closure, but since we want the code to be as elegant as possible I chose this form. Before I go into details of what is going on under the hood, we need to see the other half of the equation so we can better understand what’s going on. Here’s the implementation of the withRole method:
public void withRole(String role, {=>void} block) {
if ( roles.contains( role ) ) {
block.invoke();
}
}
Under the covers, the definition of the closure is the ugly {=>void} block. That’s telling the compiler to create an anonymous interface that has a method named invoke with no parameters and returns a void. Ok, time to take a breath. If we want to add parameters to the invoke method, we have to add them as a comma separated list in front of the => symbol. The void after the symbol is the return type. The implementation of this anonymous interface is assigned to the variable name block. There’s a bit more to it, and you can reference variables declared outside the block—but for the purposes of our conversation let’s keep it simple.
When we pass in our implementation, we use the same basic construct except we add variable names to the parameters and the implementation after the ugly symbol. We cheated in our example by not having any parameters. You might think that because the method tells what types the variables are you could skip the type declaration. You’d be dead wrong. Consider the example the spec provides (granted this is from the original specs:
// Define it
{int,int=>int} math;
// Assign it
math = {int x, int y =>
return x + y;
};
// Invoke it
assert 2 == math.invoke(1, 1);
Edit: I had to revise my initial reactions based on the input from commenters. The Java spec has come a long way. Although it’s not perfect (and what in life is?), it is a vast improvement over what we once had. The critical part of Java closures is that they are really closures. That means that you can reference variables declared outside the closure (you can’t do that with anonymous inner classes), and they enable more flexible, robust, and readable code. At least on the calling side of things. Java will never match the simplicity and elegance of Ruby, but this time it will be much improved.
The Languages Are Different, Play to Their Strengths
What I don’t want you to do is walk away with the impression that Ruby is great and Java sucks. I work with both technologies, one because I want to and the other because I’m paid to. They both have their strengths, design idioms, and code aesthetic. The important thing is to play up the strengths of the language you are using.
Just because a solution is elegant in one language doesn’t mean the same approach translates well to another. Sometimes it’s just plain impossible. Other times, the overall approach is fantastic, but the implementation will have to have subtle differences based on the language you are using. That’s OK too. My Java ActionPack is based on most of the design principles of Ruby’s action-pack (part of Rails), but they are done in a very Java way. They evolved differently, appealing to what is considered elegant and good code for the respective languages they are written for.
Edit: It appears that there are quite a few things I don’t quite get about the Java closure spec. Until we have something solid to play with, everything said is academics. Neal Grafter is the headmaster for the spec, and he should know better than I about what can and can’t be done with it.
