| Code by Kevin | |||||
|
Subscribe to RSS Feed 2011 2010 2009 2008 2007 2006 Categories Business Software General |
home :: general
Mon, 05 Dec 2011
Upgrading to Lion Server and configuring websites
While I use some outside providers for Internet services, specifically Amazon S3 for hosting demo versions of my applications, I prefer to keep most of my Internet services in-house; the flexibility and cost-reduction that such a setup offers make the trade-off in administrative time worth it. For this purpose, I have always relied on the server version of OS X for web hosting, mail serving, and related services. It provided a robust platform, and required an investment of time to master, but was worth it. The new version of Lion server is significantly different from earlier versions of OS X Server. Rather than being a separate build of OS X that's optimized for being a server (with a $500 price tag to match), it's a $50 download from the Mac App Store called Server.app. Apple is promoting Server.app as "The Server for Everyone." That initially caught my eye, but this lower price also comes as a significantly simplified version of the previous server OS: it removes a great deal of functionality that previously existed in the server OS. For my purposes, the biggest difference (read loss) is the ability to comprehensively configure the Apache web server from a GUI. Older versions of OS X Server allowed you to define domain names and customize the configuration of each domain, all from a single interface. It put the power of Apache configuration at your fingertips without requiring you to hand-hack configuration files, with their arcane syntax. By contrast, Server.app on Lion allows you to define multiple websites, set one or two options, and turn them on from the GUI--that's about it. For someone who uses the server to host a dozen websites, this is a serious issue. It's one that other reviews have noted as well. It means that if I want to provide advanced configuration of my websites, I have to hand-edit configuration files, much as if I were managing the Apache web server on a Linux or Unix system. Additionally, Apple provides little documentation on how to do this in such a way that won't cause problems with Apache. (To clarify: I am certainly capable of hand-editing Apache configuration files, but previous versions of OS X Server discouraged this because Apple's version of Apache had many Apple-specific customizations that could be best managed from the GUI; manual changes to the config files could be overwritten by the GUI or, even worse, break Apache.) After a lot of trial and error, I finally worked out a process to configure my sites so that they would support the customizations I wanted (CGI execution, domain alias, and files with *.htm suffixes ). Here it is, with the "Code by Kevin" site as a demonstration: sudo serveradmin stop web
<VirtualHost *:80> ServerName www.codebykevin.com ServerAdmin admin@example.com DocumentRoot "/Users/kevin/Sites/codebykevin" DirectoryIndex index.html index.php /wiki/ default.html index.htm CustomLog "/var/log/apache2/access_log" combinedvhost ErrorLog "/var/log/apache2/error_log" <IfModule mod_ssl.c> SSLEngine Off SSLCipherSuite "ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM" SSLProtocol -ALL +SSLv3 +TLSv1 SSLProxyEngine On SSLProxyProtocol -ALL +SSLv3 +TLSv1 </IfModule> <Directory "/Users/kevin/Sites/codebykevin"> Options All +MultiViews +ExecCGI -Indexes AllowOverride None <IfModule mod_dav.c> DAV Off </IfModule> </Directory> ServerAlias codebykevin.com AddHandler cgi-script .cgi </VirtualHost> sudo serveradmin start web
Re-start Server.app. It should read the updated configuration files. This approach is mostly undocumented by Apple, and I have not seen it documented in its entirety elsewhere on the Web either. Part of my purpose in documenting this here is to assist anyone else who might be frustrated by the limited functionality of the GUI tools in Lion Server for Apache configuration. (It's a mystery to me why Apple removed this functionality. The other hugely complex configuration that I deal with in the server, mail configuration, can still be managed from the GUI tools in Lion Server; the workflow is a bit different, with the advanced options removed from Server.app and placed in another program (Server Admin), but it's all still there, one way or another.) I am certainly please to see the reduced financial cost of server support in Lion, but especially with web configuration, Lion Server incurs other costs. I don't want to discourage anyone from buying Lion Server, but you do need to be aware of its limitations. Tue, 08 Nov 2011Daniel Jalkut had an interesting blog post the other day (in response to a similar post by Brent Simmons) about Objective-C as a programming language: it's not just his favorite language, but instead is "the language." I take that to mean his lingua franca, both the go-to tool and the standard by which he measures other tools: By no means is it perfect. But for its elegance, and for the fact that it fulfills many of the requirements of object-oriented programming, while maintaining the familiar simplicity of C, it presently earns the title of the language for me. This prompted me to look at my own toolbox, and to ponder what might serve as "the language" for me. I have several languages that I turn to, depending on the requirements at hand. I make extensive use of both "scripting" languages--high-level programming languages that are executed by an interpreter tool--and "systems" languages--low-level compiled languages that run at blinding speed and integrate with an operating system at the deepest level. With that digression out of the way, let me highlight my go-to languages for various tasks: Somewhat to my surprise, my language toolbox is rather unusual among Mac OS X developers. Nearly every Mac OS X programming blog that you read will read like Daniel Jalkut's, expressing strong preference for Objective-C as a programming language and endorsing it as the best way--indeed, for most of these developers, the only way--to create full-fledged Mac applications. This attitude has always puzzled me. While systems programming languages offer undeniable power, and indeed Objective-C is an elegant language, the trade-off for developing in such languages is developer time; development in a compiled language is much slower than with a scripting language, mainly because of issues such as memory management (allocating enough memory in the system for the application, which is quite complex) and the code-compile-debug cycle of systems development. These issues are absent from scripting languages. Not only is the development cycle shorter with scripting languages, scripting languages can also usually accomplish a task with fewer lines of code than a compiled language. (See John Osterhout's article for a useful overview of this topic.) Because of these trade-offs, I prefer to develop applications in scripting languages--Tcl and Python are much more in my comfort zone--and save systems languages for projects that require it, such as integrating a native API into Tcl or Python. I suspect that many Mac developers view Objective-C and the available tools for developing in it (Xcode, Interface Builder) as preferable based primarily on other system languages and toolkits; if you compare Objective-C to, for instance, Windows development in C using the Win32 API, Objective-C and Cocoa do look much nicer. I also suspect that if, as a developer, you are steeped in using systems languages, that may cause you to look askance at scripting languages as lightweight "toy" languages, or, at the very least, to overlook their possibile utility and advantages for desktkop application development. Another aspect is that when Cocoa developers tend to consider scripting languages in the context of desktop app development, they most often look at how the languages bind to the entire Cococa API; Python, Ruby, and other scripting languages have full Cocoa bindings, but accessing those bindings requires an awkward coding style that is not as clean as Objective-C or as standard coding conventions in that scripting language. (That's one reason why I haven't embraced Python's Cocoa bindings, instead preferring to integrate the Cocoa API's into my Tk applications as needed via extensions to Tcl/Tk.) If I had to pick which one of my tools is "the language," I suppose I would pick Tcl--it's the linchpin for everything else that I do. My GUI's are written with Tcl's native toolkit binding, Tk, even in my Python programs. (Also Ruby, which I am in the process of learning.) If I need to add some specific native Mac integration to my applications, I usually implement that functionality as an extension to Tcl using the language's C API, or via AppleScript in some isntances. I love Tcl, especially its elegance and flexibility. Yet I would never want it to be the only language in my toolbox, and I'm glad that it's not. Having multiple languages at my fingertips makes my applications better, and exapnds the range of products I can offer my customers. Thu, 06 Oct 2011Steve Jobs passed away yesterday at the too-young age of 56. Though I never met the man, I'm taking his death personally. His work has made many things possible for myself and my family that otherwise wouldn't have been. By now the outlines of Jobs' life are well-known. After founding Apple Computer with his friend Steve Wozniak, essentially creating the personal computer indudstry, and then making the computer a tool for creativity with the Macintosh, he was forced out of the company by the new CEO he helped to recruit. Jobs then wandered in the business wilderness for a decade, founding an innovative-but-unsuccessful computer company (NeXT) and buying an innovative-but-unsuccessful computer animation studio (Pixar). Then, starting in 1996, he had one of the greatest second acts in American business history. Pixar's animation technology finally matured to the point where it was feasible to make an entire movie using the techology, and the result was the landmark movie Toy Story. Pixar went public, made Jobs a very rich man again, had a long run of hit movies in partnership with Disney, and then was acquired by Disney. And Apple, nearing bankrupty, acquired Jobs' other company, NeXT, to provide the basis of its new operating system--and brought Jobs back to Apple. Apple then began its unprecedented run of hit products, from the iMac to the iPod to the iPhone and beyond, which have continued to revolutionize technology, and is now one of the most valuable companies in the world. Jobs' work made many things possible for me. The technology he helped to create, particularly the Macintosh, allowed me, then a poet, to learn design and typesetting, which enabled me to take the written word (poetry) and render it on the page, and later on the World Wide Web. I learned to appreciate a beautifully designed book and web page. That gave me a passion for the publishing field, which is how I support my family to this day, taking the written word of poets, creating beautiful books out of them, and bringing that poetry to an audience. Later on, Jobs' creations also inspired me to learn computer and software programming, so that I could take the computer I was using and expand its capabilities. Now, software development also helps to support my family. The most important way that Jobs has inspired me, however, has little to do with the products he created, but rather his example--and not the example most people cite, of the driven, perfectionist, take-no-prisoners visionary. That example, which has passed into legend and even stereotype, is one of a brilliant but impossibly demanding leader who would alternatively inspire and bully his subordinates into realizing his vision. (One archetypal example is Jobs telling a subordinate: "You've baked a lovely cake, but then you've used dog shit for frosting.") I'm no genius, and I recognize that often compromise is necessary to get something done. No, what inspires me about Jobs is more basic--it's his grit, his persistence, his tenacity. When he was banished from Apple in 1985, he was not even 30, wealthy enough to never work again--but he still felt he had something to prove. So he founded a new company, purchased another, and nurtured both companies through a periods of slow or no growth, far outside of the limelight. When one stategy didn't work, he would try another. Eventually he found a mix of approaches that slowly brought the companies to modest profitability, and poised them for their spectacular impact later in the 1990s. That decade out of the public eye was surely humbling for Jobs. He didn't have to work. He poured tens of millions of dollars into his companies as they lost money, and watched his own net worth drop. But even as that experienced humbled him, it also matured him. And it also nurtured an inner strength and determination: he didn't give up. And the world would benefit from the fruits of those efforts, with the iMac, iPod, iPhone, and more. Jobs' techology and creativity have inspired and enabled much of my work. But as the proprietor of a publishing business (books and software) with my wife, it's Jobs' tenacity that I take the greatest instruction from. It goes without saying that since the U.S. economy's collapse in 2008, running any kind of business has been challenging. The book business is going through tremendous change with the emergence of e-books, the bankruptcy of Borders, and more; the pace of change is breathtaking. The software business has huge opportunity with the resurgence of Apple and the growth of smartphones (driven largely by Apple's iPhone), but it is also extremely competitive and challenging to reach a large customer base. It takes tenacity and persistence to meet these challenges: changing your approach when the situation demands it, pursuing new opportunities in a way that makes sense, managing costs, and more. Most importantly, it requires not giving up. If you keep persisting, then your chances of surviving and even succeeding are good. My wife and I are still in business amid all the economic turmoil--that's no small accomplishment. There are other important inspirations in my life. The poet John Haines, with whom I studied, was, like Jobs, a model of uncompromising artistic integrity. His years as a homesteader in the Alaska wilderness also provided an example of the kind of life a poet could live and where poetry could thrive, outside the context of university teaching, where many poets earn their living. Similarly, the poet Dana Gioia, with whom I corresponded, provided a model of how earn one's living. Decades before he became chairman of the National Endowment for the Arts, Gioia worked in corporate life and then as a self-employed writer/editor as he established himself as a poet and critic, writing both books of poetry and criticism that challenged poetry's marginalized place in American culture in the university. As an English Ph.D. seeking employment in a depressed academic job market in the late 1990s, it eventually became necessary for me to find another career path, and the examples of Haines and Gioia were especially helpful for me: my path took me through several years in corporate life before finally leading me to self-employment as a publisher. Still, today, as a business owner in a terrible economy, I am looking in a different direction for my inspiration: Steve Jobs. During his years in the wilderness, Steve Jobs persisted. And he wound up changing the world. I don't know if I'll change the world, but I'm going to persist regardless. That's how Steve Jobs has changed my world. Sat, 20 Aug 2011I know things have seemed quiet here lately. I'm quite busy, working on several different projects, but none are yet ready to release or announce. When they are, I'll be sure to post here. Sat, 02 Jul 2011Apart from my commercial products and my Mac libraries for Tcl/Tk, I've taken on another important duty: I'm now one of the maintainers of Tk on OS X, responsible for fixing bugs, implementing features, and assisting with releases of the core Tcl/Tk language on the Mac. If you check out http://core.tcl.tk/, you'll see some of my code--bug fixes and new features to help improve Tcl/Tk's core functionality on the Mac. (My libraries, by contrast, extend Tcl/Tk's functionality into areas that the core language does not address.) While it's unpaid and not glamorous, this is an important job. I'm helping to tend the garden that provides part of my livelihood. I've long wanted to help contribute to Tcl/Tk, and it's a real honor to be able to do so now. It's with a hugely talented group of developers, whom I continually learn from. I'm grateful that my skills have progressed to the point that I am now part of this talented group, and I'm glad I can offer some of my time and assistance. Sun, 03 Apr 2011
Blending Cocoa and Unix: Printing
I've written before about how powerful I find the Mac's Unix foundation, and how much of it I integrate into my programs. More recently I've replaced some of the Unix integration of my applications with functionality accessed via the Cocoa frameworks. With the changes I'm making to my cocoaprint Tcl/Tk library, I'm now blending the Unix and Cocoa (and Carbon) approaches in new ways. When they rejected one of my apps recently, the App Store reviewers said that one of the major issues is that the app cannot do print previewing, save as PDF, or save as PostScript. That's correct, and it's by design: I had originally designed the printing code to support sending the data to the printer only. Some initial research suggested that it wasn't possible to handle "print preview" or support PDF/PostScript with the particular printing functions I utilized, since I was not using an NSView to prepare the print data. (Technical aside: the standard Cocoa way of printing is to draw data that is represented in the window on the screen (inside an NSView display) into a printing graphics context, which is then output at the printer. My approach makes use of a more traditional Unix approach, which is to write data to a PostScript or PDF file using Unix command-line tools, and then send that file to the printer.) After doing some further research, I found that I could add the required functionality to the cocoaprint library: I was able to implement print preview and exporting to PDF and PostScript. However, I did so mostly by using Unix methods, rather than traditional Cocoa printing methods. For instance: to implement print preview, rather than writing the print data to some temporary file that is then viewed in a Cocoa window or in Preview, I simply open the existing PDF file in the default PDF viewing application (using NSWorkspace methods). To implement exporting as PDF, I simply copy the existing print file to a new location defined by the user (using NSFileManager methods). And to export to PostScript, I use the Unix command-line tool "cupsfilter" (installed on OS X as part of its Common Unix Printing System, or CUPS) to convert the PDF print file to PostScript in a user-defined location. While these functions are all called under the hood using Unix or file-system methods, they are driven from the native Cocoa print dialog (NSPrintPanel). Many aspects of the print job, including determining the target location of the print output (printer, file or preview) are also managed by Core Printing functions (Core Printing is part of the Carbon framework that has not been deprecated by Apple). I'm glad I continue to rely on the Unix tools even as I increasingly make use of Cocoa (and Carbon) API calls in my work; the availability of all three in my toolbox gives me more and more flexibility in determining how I approach a programming task, and increases the range of possibilities available to me.
Rejection as positive feedback
On paper, it wasn't a good week for my App Store submissions. Both NameFind and QuickWho were rejected; NameFind was an update, while QuickWho was a new submission. Initially, this was frustrating: NameFind was rejected for a bug that I couldn't reproduce, and QuickWho had a long list of issues. I had to query the App Store team for more information about the NameFind bug, and the worst of the QuickWho issues was going to require adding some significant functionality to one of my Tk-Cocoa extensions. Still, a few days later, I'm feeling quite good about the process and bullish on the App Store. Here's why: I have a bit more cleanup and bug fixes to do on both NameFind and QuickWho before I resubmit them, but the suggestions and requests that the App Store team have sent to me will significantly improve the user experience that these applications offer--and I can roll these improvements into my other applications, as well. I'm grateful for these suggestions and also for the personal touch the App Store team is providing through their responses in the developer forums and even over the phone. Rather than continuing to see the App Store submission process as an obstacle that delays the release of new versions of my applications, and thus sales, I've come to regard the submission process as free, professional-level usability testing for my apps--a process that leads to substantial improvements in their stability and usability. I've never had this before with my apps, and I'm glad to have it now. Thu, 03 Feb 2011I've posted an article at my website that offers an overview of the process of submitting a Tcl/Tk application to the App Store, and also delves into some of the technical issues particular to Tk-Cocoa applications. I'd like to elaborate a bit here on those technical issues. One reason NameFind was initially rejected was that, at a deep level, Tk-Cocoa accesses private Cocoa code, and this runs afoul of the App Store guidelines: no private frameworks, variables, or methods/functions can be invoked by an application. "Private" means code that is internal to the Cocoa frameworks and not exposed via documented programming interfaces (API's). Because of differences between Tk's design and Cocoa, however, it was necessary for the designers of Tk-Cocoa to hook into those private API's to ensure smooth integration between the two. Since there is no way to remove the private API's from Tk-Cocoa, how was I able to work around the prohibition against accessing them? The answer is surprisingly simple: I linked my code to the Tk-Cocoa frameworks installed with OS X, instead of bundling those frameworks with my app. The system-installed frameworks are exempt from the requirements, because they are installed by Apple. This linking has come at some cost, however. The version of Tk-Cocoa that ships with Snow Leopard is very immature; it was the first public release of Tk-Cocoa, and it has a number of bugs and rough-around-the-edges bits that were later fixed and improved. Linking to this version of the framework is taking a step back in terms of performance and polish. Fortunately, there are ways to address these issues that don't compromise the polish of my applications too much. I no long have access to native, modern Cocoa notebook tabs (the older version of Tk-Cocoa uses ancient tabs that Apple stopped using in Panther, or OS X 10.3, seven years ago), but I've been able to create an attractive if unorthodox design using a different Tk widget set called BWidgets. There are certain bugs with the application menu that I can't quite figure out how to fix, but (ironically) using an older approach to setting up my menus (calling the "apple" menu) works around the problem. And, best of all, the various library extensions I've created continue to work with no problem at all. NameFind is off to a decent start with sales, and I'm already looking at some improvements based on user feedback and the changes I'm making to the next app I plan to submit to the App Store--QuickWho. Stay tuned. Wed, 18 Aug 2010
Mac-native printing, revisited
I'm now at work on integrating my cocoaprint library into my Tk applications. As I've discussed previously, cocoaprint is a departure for me in making use of Mac-native API's for printing: Cocoa for the print dialogs, and CorePrinting for interacting with the printer. Yet the old Unix command-line tools that I've relied on in the past to help manage print jobs have not gone away completely. In fact, I continue to marvel at the power of these tools--not only the traditional Unix tools, but also Mac-specific tools in which Apple exposes Mac-native API's to a command-line interface. While I'm no longer using the "lpr" tool to send print data to the printer, I am making use of other tools in preparing print jobs:
I absolutely love the Mac's Unix foundations because of tools such as these, and even as I expand my capabilities with the Cocoa frameworks, I continue to lean on the Unix tools and the power they provide. Tue, 10 Aug 2010
Further reconsiderations of "good enough"
A few months ago I wrote that I was unhappy with certain aspects of my programs, and would spend time improving them. Of course any developer will spend time trying to improve the products he or she develops, but the reason I have to weigh the benefits of these specific improvements is that they are platform improvements--advances in the underlying toolkit that I use to develop my applications--rather than application-specific features. For instance, earlier this year I spent a lot of time developing basic drag-and-drop capabilities for the toolkit my programs use, and also developing hooks to access the Mac Services menu from my programs. These are features that I can roll into all of my programs and they enhance the user experience of my programs, but they do not extend what the application itself can do. I had planned to move away from platform improvements--which some call, sardonically, shaving yaks--but I an still unhappy with certain platform aspects of my programs, specifically AppleScript support and printing support. I had declared these good enough, but they really aren't. As a result, I'm back to shaving yaks. Here's an overview of what I'm updating:
These two projects, which I've been working on for the past month, represent the last items on my list of improvement opportunities for Tcl/Tk native integration on the Mac--at least, the last two areas that I see within my current capabilities. I hope to do official releases of them soon, and then get back to application development--and leave yak-shaving behind for a good, long time. At that point, Tcl/Tk will truly be "good enough." |
||||