How leveraging web development frameworks can strengthen your skillset.
Pylons is a lightweight web framework emphasizing flexibility and rapid development.
CakePHP is a rapid development framework for PHP that provides an extensible architecture for developing, maintaining, and deploying applications.
Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.
Ruby on Rails is an open-source web framework that's optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration.
Software Entropy: A Broken Window
One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment...
The Pragmatic Programmer
We are human and we make mistakes. Frameworks should provide a rapid way to find those mistakes.
Security should never be an after thought. Good frameworks make securing your application fairly straightforward.
1: // Pylons example of form input validation 2: // @validate decorator placed above create action @h.auth.authorize(h.auth.is_valid_user) @restrict('POST') @validate(schema=NewPostForm(), form='new') def create(self): ... 3: // And the validation code class Cleanup(formencode.FancyValidator): def _to_python(self, value, state): if value['content'] not in ['', u'', None]: value['content'] = h.mytidy(value['content']) return value class ConstructSlug(formencode.FancyValidator): def _to_python(self, value, state): if value['slug'] in ['', u'', None]: title = value['title'].lower() value['slug'] = re.compile(r'[^\w-]+', re.U).sub('-', title).strip('-') return value // Other validation rules left out for brevity class NewPostForm(formencode.Schema): pre_validators = [ConstructSlug(), Cleanup()] allow_extra_fields = True filter_extra_fields = True title = formencode.validators.UnicodeString( not_empty=True, max=100, messages={ 'empty': _('Enter a post title.') }, strip=True ) slug = UniqueSlug( not_empty=True, messages={ 'empty': _('Enter a post slug, ex: my-post-title.') }, max=100, strip=True ) content = formencode.validators.UnicodeString( not_empty=True, messages={ 'empty': _('Enter some post content.') }, strip=True ) draft = formencode.validators.StringBool(if_missing=False) comments_allowed = formencode.validators.StringBool(if_missing=False) tags = formencode.foreach.ForEach(formencode.validators.Int()) chained_validators = [ValidTags()]
1: // CakePHP example of validation rules
class Photo extends AppModel {
var $name = 'Photo';
var $validate = array(
'title' => array(
'rule' => array('notempty'),
'required' => true,
'message' => 'Please enter a valid photo title.'
),
'filename' => array(
'rule' => array('extension', array('gif', 'jpeg', 'png', 'jpg')),
'message' => 'Please enter a valid photo image.'
),
'upload' => array(
'isUploadedFile' => array(
'rule' => array('isUploadedFile', 'upload'),
'required' => true,
'on' => 'create',
'message' => 'Please upload a valid file.'
)
)
);
function isUploadedFile($params){
$val = array_shift($params);
if ((isset($val['error']) && $val['error'] == 0) ||
(!empty($val['tmp_name']) && $val['tmp_name'] != 'none'))
{
return is_uploaded_file($val['tmp_name']);
} else {
return false;
}
}
1: // Pylons example of secured form 2: // For prevention of Cross-site request forgery (CSRF) attacks. 3: // Generates form tags that include client-specific authorization tokens to be verified by the destined web app. 4: // Authorization tokens are stored in the client's session. The web app can then verify the request’s submitted authorization token with the value in the client’s session. 5: // This ensures the request came from the originating page. See the wikipedia entry for Cross-site request forgery for more information. ${h.secure_form(h.url_for(post_id=c.post.id, controller='comment', action='create'), method='post')} ${fields.body()} <div class="input"> ${h.submit('create_comment', _('Create Comment'), tabindex=6)} </div> ${h.end_form()
1: // CakePHP example of secured form 2: // By default (without calling any methods) the Security component will make forms generate a hash to ensure that they haven’t been tampered with. var $components = array('...', 'Security');
1: // Pylons examples of restricting action by method
@h.auth.authorize(h.auth.is_valid_user)
@restrict('POST')
def delete(self, id=None):
try:
id = int(request.params.getone('id'))
except:
abort(400)
1: // CakePHP examples of restricting action by method 2: // Setting rules at a global level if(isset($this->Security)) { $this->Security->requireAuth('admin_delete', 'admin_edit', 'admin_add'); $this->Security->requireDelete('admin_delete'); $this->Security->requireGet('admin_confirm_delete'); } 3: // Setting rules in an action function admin_edit($id = null) { if (!$this->validId($id)) { $this->Session->setFlash(__('Invalid Photo', true)); $this->redirect(array('action'=>'index')); } if ($this->RequestHandler->isPost()) { if ($this->{$this->modelClass}->save($this->data)) { $this->Session->setFlash(__('Your photo has been saved.', true), null, null, 'succ'); $this->redirect(array('action'=>'index')); } else { $this->Session->setFlash(__('The photo could not be saved. Please, try again.', true), null, null, 'err'); } } if (empty($this->data)) { $this->{$this->modelClass}->recursive = -1; $this->data = $this->{$this->modelClass}->read(null, $id); if(empty($this->data)) { $this->Session->setFlash(__('Invalid photo.', true), null, null, 'err'); $this->redirect(array('action'=>'index')); } } }
Providing your application with pretty urls can improve user experience, as well and provide a consistant interface to your application.
Reverse Routes!
If you look for them, you'll find more opinions regarding frameworks than you could possibly care to read. My personal feeling is that:
YES! Do it