Sunday, July 26, 2009
Google Wave
And now imagine that you have it in one tool - not only those additional steps go away - but it also opens the way for new features like seeing a pointer to the part of the code that the other person is talking about, seeing his edits in real-time and commenting on them immediately etc.
This is why I believe in convergence of communication tools.
Friday, July 17, 2009
Nothing is forever
Now one would ask why write a library that is useful only temporarily? Why not include at once all the parts needed in the final product? There can be several reasons:
- something that is only a part of the scaffolding in one project can stay in the final solution in another one
- the author of the library might not yet fully understand the problem, and it can take years to reach the right abstraction
- the distribution of possibly needed modification can be so uniform that there is no reason to concentrate on one of them more than on another one and it is virtually impossible to cover them all
- and finally: nothing is forever - you never know where a project will go in the future and what you'll need to change
A good example (of the third point) are code samples from manuals - you copy them to quickly get something working - but later you modify it and sometimes you change every character from the original. Another one can be the scaffolding code in Rails - you can debate if it fits the first or the second or other points - but it was useful to a lot of people.
Every library can be used as scaffolding - so why not accept this and help the developers in using it that way?
Monday, July 13, 2009
CPAN and code reuse
And what with applications?
Thursday, July 09, 2009
Code reuse styles
I wonder why it is like that. There are some technical differences that lead developers in one or the other direction - but there is also a cultural/psychological cause. Doing some self-analysis I must admit that I am not really enthusiastic about contributing to a Perl CMS (like for example Bricolage) - in my view all the already-build solutions use obsolete libraries. I'd rather contribute to building the perfect library - then code an extension to Bricloage. I have the feeling that I am not alone in that crazy perfectionism around Perl hackers. PHP clearly wins here with more pragmatic approach.
Monday, July 06, 2009
Deprecated code analyzer for HTML::FormHandler
Saturday, July 04, 2009
Is using the Catalyst 'forward' method a cargo cult?
And when it is not enough? What are really the differences between:
$c->forward( 'some_action' )
and the standard Perl:
$self->some_action( $c );
As far as I know the only two differences are that the first call is called in an eval and that it is logged in the debug output (if it is switched on), maybe there are some other minor differences, but, I am sure, nothing dramatical. It can helpful/needed sometimes (and othertimes that eval can be a nuisance), but it is also easy to add. Of course this is the simplest case - 'forward' signature is more complex and it does amazing things for finding the action "by it's private name" - but for most of the cases you ain't gonna need it and you can use ye old Perl syntax to make the call and spare yourself learning how to pass parameters to the forward call.
Related reading: Premature Flexibilization Is The Root of Whatever Evil Is Left - a reddit discussion.
Wednesday, July 01, 2009
Functional versus Unit testing
Also discussed at Hacker News
Monday, June 29, 2009
InstantCRUD and FormHandler
Friday, June 26, 2009
Iron Man Blogging Challenge
There is just one small nitpick - if the goal is: "to promote the language to the world outside the Perl echo-chamber" then the rule that the all the posts need to be about Perl is misguided. If we want to talk to "the world outside the Perl echo-chamber" then we need to talk about the subjects that they care about. I can understand why we need some focusing - and posts about what you had for dinner are not the best way to promote the language - but it will be much easier to engage the outside audience if we wrote about general programming subjects. Look at advertisings - they don't talk about the advertised brand all the time, the more subtle the link is, the more engaging they are.
Update: I should have added that this post was inspired by Gabor Szabo: http://szabgab.com/blog/2009/06/1245788806.html
Saturday, June 20, 2009
CatalystX::Comments - RFC
Here is the current API - any comments are welcome. First you need to declare the controller using the new Moose style:
package RavLog::Controller::View;
use Moose;
BEGIN {
extends 'Catalyst::Controller';
with 'CatalystX::Comments::ControllerFormRole';
}
has model_name => ( is => 'ro', isa => 'Str', default => 'DB' );
The important part for us is of course
with 'CatalystX::Comments::ControllerFormRole', the model_name attribute should hold the name of the model CatalystX::Comments will use to store the comments.After the declarations you can use CatalystX::Comments to put the comment form on the stash:
sub view : Chained('base') PathPart('view') Args(0)
{
my ( $self, $c, $id ) = @_;
...
$self->stash_comment_form( $c, $self->article->id );
}
That's the whole controller part - what it handles is generating the form for display and saving the submitted comments. In the view templates you need to add:
[% comment_form.render %]
For displaying the comments themselves ravlog already had some template code and I did not change it.
Next is the model part. The library assumes that the DBIC model contains a Comment Result class like that one in ravlog. Of course it does not need to have all of the columns, and can also have other columns - but these are the columns that will be filled by the CatalystX::Comments form. Ideally that model part should be a Result base class - so that it can be subclassed and adapted to local circumstances (for example the belongs_to relationship to article needs to be changed), but for now I don't know how to do that.
Now some more details. Thanks to html_prefix all parameters sent from this form are prefixed with the form name - so this form can be added to pages with other forms, it will recognize it's parameters. The comments are saved only when the HTTP method used is POST, and after a successful comment creation the user is redirected to the same page (this seems a bit constraining - but see next paragraph - this is only meant to be temporary solution - I try to keep the API simple).
Of course I understand that this can never cover the needs of a comment sub-system in a mature social web site. I am thinking about it as more of scaffolding - code that let's you quickly develop a feature, see how it integrates with the rest of the user experience, formulate a more complete requirements list - and replace it part by part.
Friday, June 19, 2009
On Scaffoldings
Scaffolding is a wonderful metaphor - and the brilliance of it shows in how it transcends the original area of code generation where it was introduced in Rails. It can be applicable to any reusable software component meant to be temporary support and to be replaced later. An example of that are code samples in manuals - you copy them just to have something working, but then you modify it and nearly completely replace the original code. And since nothing is universal and no library is ideal - it can be used as a generic measure of how well a library supports this iterative development style. And this brings me to the question - what are the qualities of a good scaffolding? One is that it needs to be gradually replaceable.
Saturday, June 13, 2009
Module Rank and Informed Choice
But it all still relies on people choosing the right modules for their own projects - I believe this is a good assumption, the popular "The Wisdom of Crowds" shows why - but still it can be improved by people doing more informed choice. This was my motivation behind my API design blog post. Design of APIs is tricky and subtle and there are things that you just don't spot until it is too late, or alternatively there are deficiencies that are invisible for the seasoned user because he is used to the quirks, he internalized them and he uses the API automatically without thinking.
Sunday, June 07, 2009
Form rendering and CSS
I started reviewing the options and it seems that there are three general approaches to having aligned forms:
- tables
- divs
- lists
- no additional markup
Plus some appriopriate CSS. I think the 'no additional markup' option could never accommodate for error messages, so I leave this one out. This leaves me with three options. I am sure that not everything can be done in each one - but I think we can add a 'style' parameter to the renderer to make it configurable.
Next thing is the recently popular CSS grids - anyone using them? They seem like a nice option for someone needing some universal defaults and the SenCSS example even contains a form styled in two ways (vertical and horizontal alignments) - but would it work with error messages? And the Blueprint one even shows a div with the error class - but how that is to be inserted into the form? I guess each one requires it's own way of HTML structuring.
Friday, June 05, 2009
Packaging cross cutting Catalyst features
To try out what can be done about that I decided to write a generic comment system for Catalyst (+DBIC, TT and FormHandler). I've already posted the the first code samples to the Catalyzed wiki. The form code and the controller stuff seems closed - it does not need to refer to things from outside but in the DBIC declarations the belongs_to relation of the comments needs to relate to an external table and it's primary key (I assume that comments belong to an article/post/something). How that can be made configurable?
Wednesday, May 27, 2009
API design
There are many aspects of quality - here I would like to focus on the APIs. The problem with APIs is that their shortcomings are much more subtle than let's say bugs. Many of them are just inconveniences - things that you stop to see once you get accustomed to them, and all of them require some experience or theory just to understand that it can be done better. Arguments about APIs can become dangerously subjective. We are in dire need of API theories, objective measures to evaluate them - and here I try to compile a list of on line resources on that subject.
How To Design A Good API and Why it Matters (from Google Tech Talks)"
- see also an ACM paper with the same title and a nice abstract in the form of bullet points.My take-away points (the most non-obvious or potentially useful in arguments):
- write examples from the very start and build the API from use cases
- good names are important - API is language
- "when in doubt leave it out"
- implementation somtimes leaks out to the API
- for inheritance document self-use pattern (how methods use one another)
- "don't make the client do what the module can do"
- you can't please everyone so aim to displease everyone equally.
The Little Manual of API Design
Characteristics of good design:
- Easy to learn and memorize
- Leads to readable code
- Hard to misuse
- Easy to extend
- Complete
Again stress on writing use cases and code using the API during the design process - and one surprising but seemingly valid point: "prefer specific names to general names".
API Design Matters
This one is mostly arguing why API design matters - but there are a few points worth noting:
- always design the API from the perspective of the caller (rather obvious)
- again start with use cases
- there used to be much more programming from scratch - now we use more libraries and designing API becomes more and more important, but this is not yet reflected in university curricula (this is exactly the intuition that led me to this blog post)
Designing and Evaluating Reusable Components
The needs of the programmer changes as her project proceeds and it is important to account for that fact when writing the API. In particular more advanced projects usually need more granular APIs while at the beginning they are only an obstacle.
API design guidelines
- my question on Reddit.Update: Read Curing Python's Neglect - it's not really about Python in my opinion - and it is about how people get used to bad APIs and stop noticing the ugliness of them.
Tuesday, April 21, 2009
Constraints and Types (in Moose)
If that is not yet clear - let's take the example of checking the age of a application user (from his provided birth date). The question if a user with a given birth date can legally participate in a web forum cannot be answered without knowing what is current date - it is not a property of the birth date alone - but of it's relation to the current date. I think that using the term 'type' for this kind of constraints can be confusing, even though technically in Moose this is possible to declare this.
Saturday, April 04, 2009
Roles for FormHandler
package BookDB::Form::BookWithOwner;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Model::DBIC';
has '+item_class' => ( default => 'Author' );
has_field 'title' => ( type => 'Text', required => 1 );
has_field 'publisher' => ( type => 'Text', required => 1 );
has_field 'owner' => ( type => 'BookDB::Form::BookOwner' );
This should be quite self-explanatory for anyone working with forms (and DBIC).
Now - I think Model::DBIC should be just a role here, but that is just a side track. The real question is about the fields here - ideally I would want that doing:
with 'HTML::FormHandler::Model::DBIC';
(this is after it is made a Role) - would add appriopriate methods to the fields - an example here could be validation of fields that need a unique value. I would like to not need to change the definitions above to:
has_field 'title' => ( type => 'Text::DBIC', required => 1 );
Fields like 'owner' above which are Compound fields and work mostly like a form itself and need to load the options for SELECT boxes from the model, set the values of fields from a database row etc:
package BookDB::Form::BookOwner;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Field::Compound';
with 'HTML::FormHandler::Model::DBIC';
has '+item_class' => ( default => 'User' );
has_field 'user_name';
has_field 'fav_cat' => ( label => 'Favorite Book Category' );
has_field 'fav_book' => ( label => 'Favorite Book' );
has_field 'occupation';
has_field 'country' => ( type => 'Select' );
Ideally this definition should not need 'HTML::FormHandler::Model::DBIC' - applying this role to the root form should be enough.
Tuesday, March 31, 2009
Roles and data structures
You can start with defining the data structure and one of the aspects as the 'primary package' - and then add the other aspects as (Moose) roles. This is how it is started in FormHandler - the primary aspect here is the data processing and validation - then saving the the database is added as a role (so you can use it with different data store libraries DBIx::Class, Class::DBI and in the future all the other), the same with rendering - it is a role added to the form class. This is all nice untill you realize that in this way you add the additional roles only to the main form object - but not to the fields (i.e. nodes in the tree) - so you can walk the fields and do the stuff - but you regress here to mostly procedural code.
What we need is to somehow add this role globally to all the field and form classes used.
Tuesday, February 17, 2009
Hierarchy of code reuse
- Code generation and cut and paste: unconstrained modifications
- Inheritance and passing callbacks: modifications only at the method granularity
- Normal libraries: no modification of existing algorithms - only composing them into larger constructions
Thursday, January 29, 2009
Reading "Design Principles and Design Patterns"
I think the real takeaway is "Stable packages should be abstract packages" - where stable for the author means 'many other packages depend on that one'. The problem with translating that to dynamic languages is that the most abstract (in the OO sense) packages, the pure interfaces don't need to be written down in code at all. Duck typing gives us a great flexibility - but it also means that there is no requirement to write down the abstract interfaces - and if there is no additional pressure then they will not be defined by the programmers.
Another problem with translating the ideas into dynamic languages is the meaning of the word 'depend'. With static typing it can be clearly defined by the need to recompile the package if there is some change in the package it depends on. For dynamic typing this needs to be defined in some more subtle ways - basing it on the type of the coupling between the packages.