Entries in Programming (99)

Saturday
May222010

Learning CodeIgniter

I have just come across this series of videos on CodeIgniter by Shawn McCool:

Having worked my way through the first three, I can say that they are better organised and better presented than the more extensive CodeIgniter from Scratch series by Jeffrey Way and Burak Guzel.  In addition, McCool seems a more experienced developer and provides a lot of background details and explanations that Way & Guzel just skate over.  McCool's videos seem altogether more 'professional'.

If you are looking to learn CodeIgniter I would recommend that you use both McCool's and Way & Guzel's videos, along with the online Codeigniter User Guide, which is excellent.  I would suggest that you avoid the currently available books, which seem to be superficial and riddled with errors.  At least, be sure to read the reviews on Amazon.com before you spend money on any of them.

Wednesday
May122010

The CodeIgniter End-of-File Comment Convention

From the CodeIgniter User Guide:

The PHP closing tag on a PHP document ?> is optional to the PHP parser. However, if used, any whitespace following the closing tag, whether introduced by the developer, user, or an FTP application, can cause unwanted output, PHP errors, or if the latter are suppressed, blank pages. For this reason, all PHP files should OMIT the closing PHP tag, and instead use a comment block to mark the end of file and it's location relative to the application root. This allows you to still identify a file as being complete and not truncated.

INCORRECT:

<?php

echo "Here's my code!";

?>

CORRECT:

<?php

echo "Here's my code!";

/* End of file myfile.php */
/* Location: ./system/modules/mymodule/myfile.php */

I agree that it is a good idea to omit the PHP closing tag, and also to mark the end of file with a comment. But I think it is a bad idea to embed the name and location of the file in that comment. This introduces an unnecessary dependency between the internal contents of a file and its name and location. It should be possible to rename or move a file without having to change its contents. Embedding the file name and location make this impossible. This is particularly ironic as one of the first operations that many people perform after installing CodeIgniter is to move the application directory up one level (see the CodeIgniter video tutorials by Jeffrey Way, for instance).

Friday
Apr092010

Cohesion, Coupling and Unit Testing

Unit testing improves designs by making the costs of bad design explicit to the programmer as the software is written.  Complicated software with low cohesion and tight coupling requires more tests than simple software with high cohesion and loose coupling.  Without unit tests, the costs of the poor design are borne by QA, operators, and customers.  With unit tests, the costs are borne by the programmers.  Unit tests require time and effort to write, and at their best programmers are lazy and proud folk.  They don't want to spend time writing needless tests.

Unit tests make low cohesion visible through the costs of test setup.  Low cohesion increases the number of setup tasks performed in a test.  In a functionally cohesive module, it is usually only necessary to set up a few different sets of test conditions.  The code to set up such a condition is called a test fixture.  In a random or functionally cohesive module, many more fixtures are required  by comparison.  Each fixture is code that must be written, and time and effort must be expended.

The more dependencies on external modules, the more setup is required for tests, and the more tests must be written.  Each different class of inputs has to be tested, and each different class of input is yet another test to be written.

Jeff Younker (Foundations of Agile Python Development, Apress, 2008, pages 141 - 142).

Never have I seen the case for unit testing and TDD put better.

Thursday
Apr012010

Redirecting Symbolic Links to Directories

Suppose you are developing a website for a Linux system and you want to release it in various stages to the users. One of the ways to do this is to have a separate subdirectory for each version and to use a symbolic link (symlink) to point to the latest one. However, redirecting the symbolic link can be a bit tricky and my first attempts ended up with the link sitting inside one of the directories, instead of at the top level. The secret is to use the -n option to suppress dereferencing. Here is a simplified example illustrating how I got it to work properly:

$ mkdir dir1
$ ln -sfn dir1 latest
$ ls -l
total 4
drwxr-xr-x 2 tristram tristram 4096 2010-04-01 22:13 dir1
lrwxrwxrwx 1 tristram tristram 4 2010-04-01 22:13 latest -> dir1
$ mkdir dir2
$ ln -sfn dir2 latest
$ ls -l
total 4
drwxr-xr-x 2 tristram tristram 4096 2010-04-01 22:13 dir1
drwxr-xr-x 2 tristram tristram 4096 2010-04-01 22:13 dir2
lrwxrwxrwx 1 tristram tristram 4 2010-04-01 22:13 latest -> dir2
$

The -s and -f options select symbolic (as opposed to hard) links and force overwriting of the existing link.  For more details see the Gnu Coreutils documentation for the ln command.

Thursday
Mar112010

Monads as Overloadable Semicolons

A comment by Heinrich Apfelmus on a post by Eric Raymond:

"A simpler way to think about monads is as a hack to turn function composition into a way of forcing the sequencing of function calls, or the functional-programming equivalent of a shell pipeline."

This is probably a good first mental approximation of the IO monad, but it’s not a good way to think about monads in general. They are best understood as imperative mini-languages where you can program your own semicolon “;“. The selection of possible side-effects is huge: state, logging, exceptions, non-determinism, coroutines, … . In particular, non-determinism does not fit the “ensure evaluation order” picture.

The equivalent of a shell pipeline is plain function composition (.) coupled with lazy evaluation, at least if the shell commands are essentially side-effect free.

And a comment by Paul Johnson on the same post:

Its important to distinguish between the definition of a monad (roughly, its a type with a couple of operators defined) and the several ways that monads are used in Haskell.

*One* of those ways is to sequence several operations in some context, and one of those contexts is “IO”. This is indeed a neat hack, but the big news is that monads are not just a way to force IO semantics into a pure language, they are a way to introduce any kind of sequencing semantics you might want. Its a bit like having an overloadable semicolon; what do you want “{x;y;z}” to mean?

For instance, for one application I wrote a threaded discrete event simulation framework in Haskell using a combination of continuation and state monads with IO (because a suspended thread is actually just a continuation). This let me write application-level code with multiple threads where “delay (hour 1)” only delayed the thread long enough for the next hours-worth of simulated events to happen in other threads, rather than 1 hour of wall-clock time.

This is important because requirements are often expressed in terms of the form “do this, then do that”, where “then” has a domain-specific meaning. If you can capture that meaning in a monad then suddenly you have code that can be read and understood by a domain expert, which greatly reduces the opportunities for error.

Page 1 ... 5 6 7 8 9 ... 20 Next 5 Entries »