I leave for vacation tomorrow morning. I wont be back until the beginning of August. It’s not as though this site follows any sort of regular update schedule, but, I thought I’d let you know anyway.
July, 2004:
Your Contact Information
In testing a new piece of software to allow me to backup my address book in my cell phone, I smashed the wrong button the wrong way and erased almost all of my contacts. Therefore, I need your information, once again. If you have a vCard, just email it to me (jim [AT] revjim [DOT] net) or my phone (pager [AT] revjim [DOT] net). If you don’t, or if you don’t even know what a vCard is, I’ve setup a form you can use to “give me your contact information”:http://revjim.net/page/addcontact/. I think it works. Try it out, we’ll see. You can use either of these methods to send me your contact information whenever it changes.
I’m not sure whose information I’ve lost. I know that some are missing (Rachelle, Alan, My Sister, Emily, Rob Tovar, Rob Howe, Sean, and some of Jaclyn), but, those are only the ones I’ve noticed so far.
Thanks for helping me clean up my mistake.
The battle of PHP templates
There is one debate over within PHP that many people fail to fully understand both sides of. Lots of people who should know better make constant claims regarding the use of one method, and blindly praise the use of the other. Of course, I’m talking about PHP Template Engines.
For those that don’t know, a Template Engine (at least in the PHP realm) is a PHP class that uses an advanced form of variable substitution to allow you to define the actual text-based (HTML, RSS, XML, E-Mail message, etc) output of an application seprately from the application itself.
Most people writing any form of large application would agree that this is a good thing. Application code becomes difficult to read when it is littered with HTML tags and other outputs that are meaningless to the actual application code flow. The debate begins when people start to discuss how that Template Engine should operate. Once there is agreement that the layout code should not be intermingled with the application code, there are two schools of thought with two implementations each.
First, there are those that believe that, since PHP itself *is* a template language, PHP should be used as the language in which the template code is written. This is implemented in one of two ways. One can simply include a PHP file that contains template code. This is dirty, in my opinion, as you are either required to have all of the template variables you are going to use in the global namespace or, you must make ugly calls to some sort of template variable class in order to retrieve them. The second method, the way “PHPSavant”:http://phpsavant.com/ does it, it to use a PHP class to handle variable scoping, file includes, plugins, and other features. While this certainly uses more overhead than a simple PHP include, the organization and readability of the layout code is drastically improved and the performance hit is well worth it for anything but the simplest of pages.
Secondly, there are those that implement a “language” of their own to express logic within a template. The first implementation of this uses nothing more than variable substituion and block parsing. This means that much of the actual logic for template is contained within the code that calls the template and not the template itself. While this certainly improves the readability of application code over not using a Template Engine at all, real separation means that this layout logic should be separated from the application code entirely. This can be done in make-shift fashion if these “substitution” libraries are used correctly. However, a better alternative is to use a smarter template “language”, like “Smarty”:http://smarty.php.net/. By allowing the template language itself to be more featureful, the template logic is moved into the template itself. This allows better separation of code at with very little additional overhead as compared to simple variable substituion and block parsing.
There is one other school of thought that involves using a template that handles little more than variable substitution *and* a PHP file to handle the logic together as a single “template”. This is more complicated, in my opinion, and more difficult to debug. There are people who use this technique and do it well, however, I will not address it any further do to my ignornace of such methods.
Between these two schools of thought, there is much debate. Most arguments are against Smarty and for systems like PHPSavant. Their strongest argument goes something like “PHP is a template language, so why bother with creating, maintaining, and compiling another language entirely when PHP does everything you need”. And, in many ways, this argument is accurate. However, imagine running a large site like “LiveJournal”:http://livejournal.com/ in which regular untrusted users are allowed to redefine the templates used to display their pages. Do you really want to give untrusted users access to PHP? And even if you didn’t care about their ability to run arbitrary code, remember that the template is being run in the environment that generated the template data to begin with. This means that a even a moderately experienced PHP programmer could easily gain access to the variables and classes that were used to construct the data for the template in the first place. They could access information they don’t have permission to, alter configuration files, and have direct access to your database. Is this what you want your untrusted users doing? Probably not. So, in a case like this, PHPSavant, or any PHP-based Template Engine, just doesn’t work because it allows the user too much access. Systems like Smarty allow the application programmer to specifically limit what the user can and cannot do within a template.
But what about applications in which the programmer or site owner is the only person who will be editing and maintaining templates? Surely, if this individual decides to do something silly with the extra power they get through using PHP as a template language then that is their own fault. In this simple scenario, it perfectly acceptable to use PHP as the template language. However, imagine now an only slightly more complicated scenario. Imagine an application programmer and a site designer working together. Sure, the site designer can learn a PHP template just as easily (easier?) than they could learn Smarty Templates but, with PHP templates you run the risk that they might do something that would crash the host server, or something that “works” but is difficult to maintain due to some absurd methods being used. With Smarty Templates, they only have a limited set of functionality at their hands. If they need to do something other than what comes out of the box, they have to consult the application programmer.
I hear the nay-sayers screaming now, “but Smarty Templates require regular expression based parsing and that makes the application much slower and more CPU intensive”. Not really. When properly setup (the defaults), Smarty reparses only template files that have changed. Once parsed, they are compliled into pure PHP and stored in this fashion. Every subsequent invocation uses this compiled version until a change in the template source is detected. Yes, there is two extra “stat” calls that must take place to determine if a compiled template is available and if the template source has been changed, but, if you’re really looking for optimization, even these checks can be disabled. And it’s quite possible that the PHP you would author directly is more optimized than the generated PHP created in the Smarty compile process. And there’s really no way to measure how much more optimized since the PHP Templates are only as optimized as the PHP coder writing them is capable of.
In conclusion, though I’ve never used it, PHPSavant appears to be a terrific PHP based Template Engine. If the application you’re building will only be designed by you, a designer, or the site owner who installs the application, I’m sure it’s the way to go. However, for additional separation, greater assurance of server stability, and greater control over what the designer is allowed to do, a Smarty template will not impact performance much more than PHPSavant will (only two extra “stat” calls and, possibly, less optimal PHP code). And if you intend to let your users edit their own templates, PHPSavant isn’t even an option.
On Database Abstraction Layers
With all of this talk of the benefit (or lack there of) of database abstraction layers, I feel the need to inject a bit of clarity into the discussion. It seems that many of the people who have so much to say on this topic are also the people who neglect to see the entire picture.
First of all, a clarification. “Jeremy”:http://jeremy.zawodny.com/blog/ recently wrote regarding his belief that “Database Abstraction Layers must Die”:http://jeremy.zawodny.com/blog/archives/002194.html. He mentions that the primary purpose for using an abstraction layer is to allow an application to switch database engines with little to no code changes. He accurately points out that, in many cases, altering the database calls in your code is the easiest of the tasks involved with a database engine switch if you use proper programming methods.
bq. I use a revolutionary new programming technique. Instead of littering my code with those calls, I put my core data access layer into a library–a separate piece of reusable code that I can include in various parts of my application and… reuse!
In this respect, he’s correct. If you’re writing a custom application for use in-house, you’re not generally going to change database engines on a whim. And, if you’ve got all of your database calls wrapped neatly in a few classes serving as your application model, you don’t have to look very far to make those alterations.
John Lim, of “PHP Everywhere”:http://phplens.com/phpeverywhere/, “argues”:http://phplens.com/phpeverywhere/?q=node/view/63 that Jeremy’s thoughts on Database Abstraction are only relevant when you’re dealing with large, Yahoo-grade applications. I don’t entirely agree with this statement. Even medium-sized sites and applications can benefit from the additional speed brought forth by *not* using a database abstraction layer. And, as Jeremy said, the probability of even a medium-sized site changing database engines is low and, even if it were to happen, changing the code would be the easiest of the tasks involved when proper coding technique is uesd.
John goes on to to show that he has completely misunderstood Jeremy’s “alternative” by saying:
bq. The irony is that in the end Jeremy advocates a standard database library for managing error-handling and other execution details. BUT IT’S OK BECAUSE IT DOESN’T HAVE THE WORD ABSTRACTION IN IT. Err, Jeremy, your fly is open.
John… Jeremy is not advocating a *standard database library* to manage error-handling and other execution details. He’s advocating an application *model* filled with methods that pertain to the application at hand. And those methods just happen to use a database engine to perfrom their tasks. This is quite different from a database abstraction layer. His example doesn’t have the word abstraction in it because it isn’t a database abstraction layer at all. It’s an application model and any good programmer interested in authoring maintainable code will use an application model, regardless of whether they use a database abstraction layer or not.
So, John, before you begin pointing out the fact that someone else might have his zipper down, you ought to look at your own crotch and make sure your dick isn’t hanging out.
(P.S. I know John had the best of intentions with his writing, and his site is a valuable resource to the PHP community)
With all that being said, I don’t believe that Jeremy has taken all things into consideration when he claims that “Database Abstraction Layers Must Die!”. In an in-house application, he’s right on. However, when you are developing an application that you intend to sell to other parties or to release to the public for free, you have to take into consideration that, while you’re unlikely to switch database engines on a whim, the other people using your code might also use a different database engine than you. If you wish to cater to those people who have different storage requirements than you do, you really only have three options.
1) You can write various versions of your application model supporting different backends and allow the user to choose which model works best for them. Every time you make an API change, you have to make that same change in all of the mutations of that model. This means more work for you.
2) You can write your application model in two pieces, a base class, and an extention of that class, allowing other users to extend that class as well to support their own backend storage needs. This means that API changes might break their custom extentions if you’re not careful and also means that you’re not providing an “out of the box” solution. Of course, over time, you can work out several extensions of your base class to distribute with the application. In this case, code is more mantainable, and less likely to break or need an update for small API changes. However, you’ve got a lot more code to write and must suddenly become an “expert” on engines you may have never used before and may not even have access to.
3) You can use a database abstraction layer and leave the task of supporting new backends to the authors of that layer.
Option 3 is most likely the “slowest” of the three in regard to execution time. However, a few extra CPU cycles, in many cases, is well worth the flexibility this provides to the users of your software.
So, to summarize: database abstraction layers do, in most cases, slow down code execution. Often times they also alter the way certain features within a storage engine work, therefore, reducing the value of that storage engine considerably. And, since all database engines are not alike, many of the extended features of various engines are unaccounted for in these abstraction layers, leaving the programmer to mix abstraction layer calls, and direct calls, which is rarely a good idea, and almost always confusing. However, execution speed and backend features are not always the top priority. When flexibility and ease of maintenance is your goal, a database abstraction layer can be a very useful tool.
Another Year
Yes. Yesterday was my birthday. So add one more to that number that represents just how bald, tired, un-cool, nervous, and grumpy I am. I’ve earned it.
Thank you to all of my readers who wrote in to wish me well.
(You can read about what I did for my birthday in that “other place”:http://revjim.net/item/10064/. Also, if you don’t work for the company I work for and you asked to have the URL and I didn’t give it to you, you should probably send me another email, as, I’ve replied to everyone.)
I don’t usually make birthday resolutions, and this year isn’t any different. But I will say that I am getting more comfortable write here (and there) now that I have found a happier separation. Yes, I’m still getting used to how it all works, but it’s much easier. So, I’m not making any promises, but I’m hoping that you’ll see more focus, and more content, in both areas.
Editing a photographic collection
Several times in the past, and again today, I have been asked why it is I don’t simply publish *all* of the images straight out of my camera on to the web for my viewers to see. I’d like to attempt an explanation.
Very rarely is a professional photographer’s work presented as a giant flip-book of shot after shot after shot just as they were taken from the film or digital camera. Regardless of what the reason for the photographs are, the photographer generally wants to show only his or her best images. A portrait studio doesn’t want the purchaser to have to flip through hundreds of bad shots just to see one or two good ones. A fashion photographer doesn’t want his customer to see the images where the model’s eyes were closed, or the framing was off just enough to make the background slightly crooked. A product photographer doesn’t want to show off the photographs where the background lighting wasn’t quite bright enough to render the product surrounded in perfectly bright white.
Every collection of images is “edited” (as it is known in the business) which, for most photographers, naturally happens in several phases.
Many of my photographs from a shoot are light tests. I wasn’t concerned with how she looked or what she was doing, I was just making sure I had the proper exposure dialed in on my camera (since I work without a flash meter, and even then, a lot of film-based pros use a polaroid camera to test this very thing). There are several of these every time the lighting is changed or the model’s pose is changed enough that the lighting could be affected.
Many of the photos have her with her eyes shut, or making a bad face. This can often be anticipated, but some models are very “blinky” and others start to say something just as your finger has pressed the trigger.
Many of the shots were improved by the following shot as is part of the process that even most of the best National Geographic phtographers use (frame, shoot, then consider if you should reframe. reframe, shoot, then consider if you should reframe again. Repeat until you feel satisfied, move on to the next shot). All the shots prior to the “good” shot are only slightly different from the final image. Maybe I crouched a little lower, angled the camera slightly different, or had her turn her face just a little more away from the camera. In most cases, for every “good” shot, I’ll take 2 to 5 shots leading up to it. Why even push the button until you know you’ve got it? Who knows. But even film based photographers who “pay per shot” tend to practice this behavior.
There are a few shots that are just plain underexposed, out of focus, misframed, etc… purely a photographer’s mistake. These are few and far between, but, in a series of 140 shots, I usually manage to have 1 or 2 or these. Many photographers are good enough that they don’t get any of these. I’m not that good yet.
After weeding out all of those you’re left with about 10-20%. This is the first phase of “editing”. It removes all of the obvious junk and duplicates. If I were ever going to post anything in its “entirety” it would happen after the first phase of editing.
The second phase of editing is where the remaining images are examined for content, clarity, proper framing, meaning, etc. This is where “this one is good and this one is bad” takes place. Some images simply don’t fit the vision of the shoot: the expression isn’t right, or the hands aren’t placed as well as you thought they were. These are images that are, technically speaking, good, but just don’t fit the vision, artistically. Sometimes an effect you were going for just didn’t work out as well as you had planned or, despite your attempts, the model just wouldn’t or couldn’t do what you were looking for. For me, this phase weeds out about half of those that remained from the first cut. More experienced photographers are surely better at getting what they expect, someday, hopefully, I’ll be able to skip this phase of editing entirely.
Finally, there is the third phase of editing. In the “film” world, this happens after proofs have been made of those that made the second phase cut. The proofs are examined, areas are selected to be dodged and burned, cropping is determined, contrast is altered and many other darkroom techniques are applied. Most amatuers can’t afford this phase (unless they are a student with a dark room available to them) and most portrait studios don’t bother with it. Often times street photographer’s and photojournalists will skip it as well. However, fine art photographers, fashion photographers, and commercial photographers almost always participate in this phase of the edit. In the digital photography world, this is where the image is edited in software. I don’t mean drastic digital editing. I mean applying standard camera “filters” and conventional darkroom techniques in software.
Most often, the thrid phase of editing doesn’t cause any images to be thrown out. But sometimes, since the images are being examined more closely, a photographer will decide not to use an image in this phase.
And there you have it. 140 images quickly shrinks to about 10 or 20. 140 images becomes 14 to 28 images just by removing junk and duplicates in the first phase. This cut isn’t really a matter of “opinion”. The ones that are cut are clearly either junk or superfluous. While they might make a nice addition to a “behind the scenes” type portfolio, they certainly don’t represent your “finished” product. The remaining two edits are very opinion based, very time consuming, and result in the possible removal of images that other people might deem as “good”.
Photoshoot: Laura
Saturday night I did a photoshoot with Laura (who prefers that I don’t link to her). I took about 140 shots and ended up with 9 that I liked. A lot of the unused photos were the result of choosing a background that just didn’t work, resulting in an entire set of poses being tossed out in the editing phase.
Laura was great to work with. Jess (who helps me with every shoot) and I both commented afterwards that these photographs don’t do her beauty justice. Laura is both sexy and attractive with and without clothing. I’m incredibly lucky to have had an opportunity to work with her, and am very grateful for her time and her patience. As soon as I improve a bit more, I would be very happy to shoot her again.
You should also know that Laura isn’t always this solemn looking. I just preferred this look (partially explained below) in my editing process. She has a beautiful smile and has a tendency to do so. I was constantly asking her to smile less.
This shoot was an incredible learning experience. Despite the low hit ratio and background troubles, I think the images from this shoot really show that I learned a lot from the last. I think the lighting is a lot better than before. Additionally, in the last shoot, the model pretty much posed herself while, in this shoot, I had to do a lot more. This is good because it forced me to learn for myself what looks good and what doesn’t. Here’s what I learned:
# Despite the fact that almost every house in America has flooring that is a different color than the walls, this doesn’t look good in a photograph. The images are much more pleasing when the background matches the floor covering.
# Unless you are willing to overexpose your subject or the background, black hair will disappear on a black background. This isn’t a bad thing, but it can be upsetting if it wasn’t what you were expecting.
# Asian people present a unique set of problems (just like white people, black people, large people, children, etc) when being photographed. Generally speaking, their eyes tend to get smaller when they smile. This means that, if you aren’t specifically counteracting this you could end up with an image that doesn’t have the same sparkle in the eyes that you’re looking for.
# A light directly facing the chest will cause the skin on the chest to become brighter than you’d expect (and probably overexposed). A slight turn toward or away from the camera should eliminate this.
I’ve left the two most important lessons out of the list in order to emphasize it. First of all, I can’t expect to get a model to let go and allow herself to be pushed to the edge of what she is comfortable with if I am not also pushing myself to that edge. Secondly, when I work a pose, I start of with something basic, and slowly modify the pose, angle, and framing, until I get a shot that is pleasing. However, as soon as I get that shot, I stop with that pose, and move on to the next. I need to continue to work that pose just a little more, not only because an even more interesting shot might result from it, but also because that ensures I get a few shots of that “final” image, just in case one of them caught the model with her eyes closed, or a funny expression on her face.
My favorite images from the shoot are “Desire”:http://photos.revjim.net/laura20040703/20040703_214346, “Said Without Speaking”:http://photos.revjim.net/laura20040703/20040703_220344 (NSFW), and “Pure Innocence”:http://photos.revjim.net/laura20040703/20040703_215437.
bq. “Laura 2004-07-03″:http://photos.revjim.net/laura20040703 (some NSFW)
As always, your comments and suggestions are greatly appreciated.