205 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			XML
		
	
	
	
		
		
			
		
	
	
			205 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			XML
		
	
	
	
|  | <chapter> | ||
|  | <?dbhtml filename="programming-guidelines.html"?> | ||
|  | <title>Programming Guidelines</title> | ||
|  | 
 | ||
|  | <para> | ||
|  | If you're contributing code back into LiveJournal, be sure to follow | ||
|  | the following guidelines: | ||
|  | </para> | ||
|  | 
 | ||
|  | <!-- SECURITY --> | ||
|  | <itemizedlist> | ||
|  | <title> | ||
|  | Security | ||
|  | </title> | ||
|  | <listitem><para> | ||
|  | all GET/POST form values go into %FORM into BML, but check | ||
|  | <function>LJ::did_post()</function> on critical actions.  GET requests can be easily | ||
|  | spoofed, or hidden in images, etc. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | never read in arbitrary amounts of input | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | never use unsanitized data in a command or SQL | ||
|  | </para></listitem> | ||
|  | </itemizedlist> | ||
|  | 
 | ||
|  | <!-- GENERAL --> | ||
|  | <itemizedlist> | ||
|  | <title> | ||
|  | General | ||
|  | </title> | ||
|  | <listitem><para> | ||
|  | BML pages shouldn't interface with the database much.  Use the | ||
|  | LJ::* API & the protocol handler. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | always use the <function>LJ::</function> functions that take an explicit database | ||
|  | handle.  don't use the old <function>main::</function> functions that use the global | ||
|  | $dbh. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | all files should have <sgmltag><LJDEP></sgmltag> edge dependency somewhere, usually | ||
|  | at the bottom. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | using userids (integers) for things is better than using | ||
|  | users (strings), except in URL arguments, where pretty | ||
|  | is more important than speed. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | in BML page, use BML blocks defined in global.look:  | ||
|  | LJUSER, P, H1, H2, STANDOUT, HR, etc... | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | all HTML should be XHTML compliant.: | ||
|  |   <itemizedlist> | ||
|  |   <listitem><para> | ||
|  |      lower case tags, <sgmltag><BR></sgmltag> ⇒ <sgmltag><br /></sgmltag> | ||
|  |   </para></listitem> | ||
|  |   <listitem><para> | ||
|  |       quotes around attributes <font face="helvetica"> | ||
|  |   </para></listitem> | ||
|  |   <listitem><para> | ||
|  |     no bare & chars ... always escape them: &amp; and | ||
|  |          <a href="foo.bml?a=1&amp;b=2">...</a> | ||
|  |   </para></listitem> | ||
|  |   </itemizedlist> | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | use of multiple files to do one function is deprecated.  there | ||
|  | should no longer be "foo.bml" and "foo_do.bml" like there used | ||
|  | to.  that's ugly. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | tab is a formatting command, not a character.  (TODO: add note | ||
|  | about save hooks for emacs & vi) there should be spaces in the | ||
|  | files, not tab characters | ||
|  | </para></listitem> | ||
|  | </itemizedlist> | ||
|  | 
 | ||
|  | <!-- DATABASE --> | ||
|  | 
 | ||
|  | <itemizedlist> | ||
|  | <title>Database</title> | ||
|  | <listitem><para> | ||
|  | check your db index usage... mysql's "EXPLAIN" is your friend. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | between LOCK TABLES & UNLOCK TABLES, never call a subroutine. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | check the DB error code after an SQL statement.  just because | ||
|  | it worked once and the SQL is correct, that doesn't mean the | ||
|  | table might not go corrupt, a disk might fill up, or index | ||
|  | space within the file might not fill up.  errors happen. | ||
|  | deal with them. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | preferred way to break up a long SQL query: | ||
|  | <programlisting> | ||
|  |   $sth = $dbh->prepare("SELECT cola, colb, colc, cold FROM foo ". | ||
|  |                        "WHERE colb<>cola AND colc=22"); | ||
|  | </programlisting> | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | Note on variable naming: | ||
|  | <informaltable> | ||
|  | <tgroup cols="2"> | ||
|  | <tbody> | ||
|  | <row> | ||
|  | <entry><computeroutput>$sth</computeroutput></entry> | ||
|  | <entry>statement handle</entry> | ||
|  | </row> | ||
|  | <row> | ||
|  | <entry><computeroutput>$dbh</computeroutput></entry> | ||
|  | <entry>one database handle (usually the master)</entry> | ||
|  | </row> | ||
|  | <row> | ||
|  | <entry><computeroutput>$dbs</computeroutput></entry> | ||
|  | <entry>set of database handles [master(, slave)]</entry> | ||
|  | </row> | ||
|  | <row> | ||
|  | <entry><computeroutput>$dbr</computeroutput></entry> | ||
|  | <entry>read-only slave db handle (used for selects)</entry> | ||
|  | </row> | ||
|  | <row> | ||
|  | <entry><computeroutput>$dbarg</computeroutput></entry> | ||
|  | <entry>argument that can take a $dbh/r or $dbs</entry> | ||
|  | </row> | ||
|  | <row> | ||
|  | <entry><computeroutput>$remote</computeroutput></entry> | ||
|  | <entry> | ||
|  | hashref of remote user, based on cookies.  will contain 'userid' and | ||
|  | 'user' params, unless faster get_remote_noauth was used, in which case | ||
|  | only 'user' will be present. | ||
|  | </entry> | ||
|  | </row> | ||
|  | <row> | ||
|  | <entry><computeroutput>$u</computeroutput></entry> | ||
|  | <entry>a user 'object' (a hashref)</entry> | ||
|  | </row> | ||
|  | </tbody> | ||
|  | </tgroup> | ||
|  | </informaltable> | ||
|  | </para></listitem> | ||
|  | </itemizedlist> | ||
|  | 
 | ||
|  | <!-- Performance and Scalability --> | ||
|  | 
 | ||
|  | <itemizedlist> | ||
|  | <title>Performance & Scalability</title> | ||
|  | <listitem><para> | ||
|  | Large chunks of code should be preloaded in libraries.  Code | ||
|  | in BML pages is re-evaled on every request, so it should | ||
|  | be small.  If you need a lot of code, put it in a library | ||
|  | and load it in cgi-bin/lj-bml-(init|local).pl | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | don't write temporary files to disk... all LJ code should be able | ||
|  | to run on a cluster of web servers with no session persistence | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | if you're calling a function with a $dbarg parameter and you | ||
|  | have both a <computeroutput>$dbs</computeroutput> and <computeroutput>$dbh</computeroutput> available, call the function with | ||
|  | your <computeroutput>$dbs</computeroutput> ... otherwise the function and all its callees | ||
|  | can't ever use the slave databases. | ||
|  | </para></listitem> | ||
|  | </itemizedlist> | ||
|  | 
 | ||
|  | <!-- Patches --> | ||
|  | 
 | ||
|  | <itemizedlist> | ||
|  | <title>Patches</title> | ||
|  | <listitem><para> | ||
|  | all patches sent in should be in diff -u format | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | don't send in patches that comment out old code.  if | ||
|  | we want the old code, we'll go get it from CVS.. that's | ||
|  | what it's for | ||
|  | </para></listitem> | ||
|  | </itemizedlist> | ||
|  | 
 | ||
|  | <!-- Perl Style --> | ||
|  | 
 | ||
|  | <itemizedlist> | ||
|  | <title>Perl Style</title> | ||
|  | <listitem><para> | ||
|  | <computeroutput>foo()</computeroutput> looks prettier than  | ||
|  | <computeroutput>&foo()</computeroutput>.  let perl 4 die. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | lines longer than 80 characters are okay, but not great. | ||
|  | </para></listitem> | ||
|  | <listitem><para> | ||
|  | if you're in package LJ and calling an LJ::* API function, | ||
|  | go ahead and type the extra four characters (LJ::) even  | ||
|  | if they're not necessary... being explicit is nice for | ||
|  | the reader. | ||
|  | </para></listitem> | ||
|  | </itemizedlist> | ||
|  | 
 | ||
|  | </chapter> |