Search Results: "cas"

14 May 2009

Julian Andres Klode: PHP, MySQL, PostgreSQL, etc.


Well, I m currently writing a PHP and SQL application at school, so here are some of my thoughts on the problems I encounter. PHP is crap Many PHP applications are low quality applications. The problem is that PHP makes it hard for developers to write good applications. PHP developers tend to use many global variables, global code, and not many classes or functions. And when writing applications for the web, PHP makes it easy to mix PHP and HTML, in my opinion even too easy. Well-written applications follow some basic rules. First, separate your code into functions and classes, and (2) split your code over multiple files. And there is one rule which is especially important for non-commandline applications: (3) seperate logic and presentation. This means if you write a web application, use a template engine. PHP error and exception handling is also an interesting topic. The problem here lies in the distinction between the both. In my opinion, there should only be one way to handle such stuff: Using exceptions. Exceptions are a very widespread way to program today, and are used in languages like Java and Python for cases where PHP uses errors. The concept of PHP s errors results in code like @do_something or die("blah"); being written in libraries which is a problem as it clearly violates rule (3) I wrote above, because there is no way to catch this die() error. Furthemore, PHP has no clear concept of namespaces in the current stable versions (< 5.3). PHP 5.3 finally gets namespaces, but using a backslash character, which looks really bad and makes everyone think of eithers Windows systems or escape characters. There are even more problems with PHP. From time to time, PHP just crashes with a segmentation fault. MySQL vs. PostgreSQL MySQL seems to have many problems with checking data, which can confuse me. It got better in MySQL 5 with the introduction of the new sql_modes like STRICT_ALL_TABLES and TRADITIONAL. And using storage engines like InnoDB also allows you to take advantage of stuff like foreign keys and transactions. But MySQL is still problematic. For example, in an application I wrote I had multiple entries identified by a numeric id (an INTEGER). One day, I wanted to check whether my error handling was OK and requested an entry with the invalid ID 1X , which resulted in SELECT * from A where id='1X';. Now I expected to get an error or at least no result, but MySQL happily proceeded with the query and returned the entry with the ID 1. I tried the same thing on PostgreSQL and got an error message that 1X is not integer, as I expected it. As another example, when I run the same PHP application using PDO on a MySQL database and a PostgreSQL database, I always get strings from the MySQL database whereas I get integers from PostgreSQL if the columns are integers. Another thing which PostgreSQL does better than MySQL is password encryption. MySQL only provides access to the standard crypt() function and by default only generates DES passwords. It allows other methods to be used (although not all are available everywhere and therefore not documented), but it provides no way to create a salt for them, which makes them not very useful. PostgreSQL in contrast provides less encryption methods but it provides the gen_salt() function which can be used to generate salts for blowfish encryption (gen_salt('bf')). Another problem is that MySQL simply ignores references when they are added to the column definition instead of a separate FOREIGN KEY . Because MySQL gives no errors when a feature like REFERENCES is not supported, developers may think that the feature is supported and write code using this feature just to realize later that what they wrote does not what they want. And you can t write AGPL applications using MySQL client libraries, because MySQL is GPL-2 which is incompatible with the AGPL. You might think that the FOSS License Exception helps here, but this only lists (among others) the GPL-3. Or am I wrong? But PostgreSQL has other problems, at least when it comes to the performance of the information_schema.columns view. This may be related to the fact that PostgreSQL has > 1000 rows whereas MySQL only has 250. And PostgreSQL may be a bit harder to configure. Final words All in all, PHP and MySQL are not the best choices for writing applications. They are to tolerant, and do not treat errors in an acceptable way by aborting the current action. I can get around some problems in PHP by using error handlers which raise exceptions and setting error_reporting to E_ALL, but in fact this should be the default. MySQL problems can be solved to a large extend by setting sql_mode to TRADTIONAL and using InnoDB databases, which should in my opinion be the default and not an option. My recommendation is to use PostgreSQL servers and for the applications: use frameworks (if you are allowed to, which may not be always the case [e.g. when you are learning SQL, using a ORM is clearly the wrong way]), document your code, separate your code into classes and functions, and make sure you are not using to many global variables. And use a SCM to track your changes. Posted in General

Marco d'Itri: sarge domUs in a lenny dom0

In a service provider environment it is often required by customers to support old server installations for much longer than it is recommended by vendors. Recently I had to move some Xen VPSes running Debian 3.1 to a modern Xen host running lenny and the 2.6.26 kernel. Since Xen is a FPOS and has been unable for years to maintain a stable ABI, I always use in the domUs the same kernel version of the dom0. The Debian Xen kernels require using an initramfs to load the paravirtualized block device driver and mount the root, at least. This would usually not be a big deal, but in this case breaks the VPS because the lenny version of udev is started in the initramfs and the system has either no udev or the old sarge version. The most immediately visible effect is that /dev/pts does not exist, which makes ssh less than useful. This is my solution:
dpkg --purge hotplug udev
printf '#!/bin/sh\nmkdir /dev/pts\n' > /etc/rcS.d/S02mkdir
chmod +x /etc/rcS.d/S02mkdir

13 May 2009

Lucas Nussbaum: UDD and packages metrics

Peter Eisentraut played with Ultimate Debian Database, and wanted to create a maintenance effort metric by multiplying each package s installed size by its popcon. His query is:
SELECT rank() OVER (ORDER BY score DESC), source,
sum(installed_size::numeric * insts) AS score
FROM packages JOIN popcon USING (package)
WHERE distribution = 'debian' AND release = 'sid'
AND component = 'main' AND architecture IN ('all', 'i386')
GROUP BY source, version ORDER BY score DESC LIMIT 30;
Besides all the interesting things that I learnt by looking at his query (rank(), and a bug in UDD because installed_size should really be numeric to avoid the conversion), Peter had a problem with his query: linux-2.6 is missing from the results, while it should obviously have a large popcon and a large install size. The problem is that the binary packages for linux-2.6 often change, so they don t get very high in popcon. The unstable kernel package gets a ridiculous popcon score: select package, insts from popcon
where package in (select package from packages where source ='linux-2.6' and release='sid')
order by insts desc limit 30;
package                             insts
----------------------------------+-------
linux-libc-dev                      38703
linux-source-2.6.29                   614
linux-headers-2.6.29-2-common         256
linux-image-2.6.29-2-amd64            239
A solution could be to change the metric to be: MAX(insts over all binary packages from this source package) * SUM(installed_size)
The good thing is that UDD already offers a popcon_src view, that gives the popcon score for a source package. So the query becomes:
SELECT rank() OVER (ORDER BY score DESC), source,
sum(installed_size::numeric * insts) AS score
FROM packages JOIN popcon_src USING (source)
WHERE distribution = 'debian' AND release = 'sid'
AND component = 'main' AND architecture IN ('all', 'i386')
GROUP BY source ORDER BY score DESC LIMIT 30;
 rank       source         score
------+---------------+-------------
1   openoffice.org      92177633504
2   qt4-x11             18503941620
3   linux-2.6           16036201020
4   gcc-4.3             14369300376
5   mesa                12962475968
6   eglibc              12581290240
7   gcc-4.4             11411296672
8   samba               10021083072
9   xulrunner            9037295424
10   mysql-dfsg-5.0      8348333532
This time, linux-2.6 shows up near the top of the list.

Peter Eisentraut: The Big Shots

As the occasional thinker about open-source development practices, communities, and issues, I have been wondering for a while: What are the largest open-source projects? What projects have the most code, the most users, and the most issues to deal with, and how do they cope?

The Debian archive should provide some insights into the first one or two questions, as it contains a very large portion of all available and relevant open-source software and exposes them in a fairly standard form. In the old days one might have gotten out grep-dctrl to create some puzzling statistics, but nowadays this information is actually available in an SQL database: the Ultimate Debian Database (UDD). (And it's in PostgreSQL. And it comes with a postgresql_autodoc-generated schema documentation. Excellent.)

So here is a first question. Well, the zeroth question would have been, which source packages have the largest unpacked orig tarball, but that information doesn't seem to be available, either via UDD or via apt. So the first question anyway is, which source packages produce the largest installation size across all their binary packages:
udd=> SELECT source, sum(installed_size)/1024 AS mib FROM packages WHERE distribution = 'debian' AND release = 'sid' AND component = 'main' AND architecture IN ('all', 'i386') AND section 
 'debug' GROUP BY source, version ORDER BY mib DESC LIMIT 30;                                                                                   
source mib
------------------+------
openoffice.org 1797
kde-l10n 648
gcj-4.4 544
vtk 465
linux-2.6 404
openclipart 353
vegastrike-data 311
ghc6 308
gclcvs 303
wesnoth 300
fpc 269
axiom 256
webkit 255
gcc-snapshot 255
lazarus 241
kdebase-workspace 226
plt-scheme 221
torcs-data-tracks 219
scilab 213
openscenegraph 211
eclipse 210
sagemath 201
insighttoolkit 198
acl2 195
kdebindings 181
atlas 165
gcl 163
trilinos 153
paraview 153
asterisk 144
(30 rows)
This produces a few well-known packages, but also a number of obscure ones. If you look closer, many of them appear to be themed around scientific, numerical, visualization, Scheme, Lisp, that sort of thing. Hmm.

Here is another idea. Take a package's installation footprint and multiply it by its popularity contest installation count. So you get some kind of maintenance effort score, either because the package is large or because you have a lot of users or both.
SELECT rank() OVER (ORDER BY score DESC), source, sum(installed_size::numeric * insts) AS score FROM packages JOIN popcon USING (package) WHERE distribution = 'debian' AND release = 'sid' AND component = 'main' AND architecture IN ('all', 'i386') GROUP BY source, version ORDER BY score DESC LIMIT 30;
rank source score
-----+-----------------------------+-------------
1 openoffice.org 12638492332
2 mysql-dfsg-5.0 3411344560
3 eglibc 3371485240
4 perl 3019183024
5 evolution 2669948000
6 samba 2308923872
7 mesa 1853902860
8 texlive-base 1684245516
9 gcj-4.3 1610495484
10 foomatic-db-engine 1608178104
11 foomatic-db 1423947704
12 inkscape 1413910080
13 qt4-x11 1258220636
14 gcc-4.3 1248741312
15 kdelibs 1021058256
16 gnome-applets 998434136
17 xulrunner 958232688
18 coreutils 954766896
19 openssl 877067672
20 ncurses 827679424
21 python2.5 815826384
22 aptitude 808161380
23 gimp 786015124
24 gnome-utils 781756328
25 nautilus 774319690
26 openoffice.org-dictionaries 761075576
27 eclipse 756072380
28 dpkg 736626200
29 openclipart 731244240
30 wine 707967500
(30 rows)
(Yeah, they run this thing on PostgreSQL 8.4 beta 1.)

I noticed linux-2.6 is suspiciously absent because of a low popcon score (?!?).

I don't want to dump the entire database into this blog post, but if you try this yourself you can look at about the first 200 to 300 places to find reasonably large and complex projects before it gets a bit more obscure. A few highlights:
  51   gnupg                           455660464
59 php5 386417572
60 mutt 381148176
83 icu 258602756
84 xorg-server 255186332
101 exim4 224857700
107 openssh 215792828
113 tar 201520400
114 postgresql-8.3 196844584
115 libx11 195856564
116 ruby1.8 194681656
272 emacs22 62047476
This is obviously still biased in a lot of ways, but it does show the major projects.

The UDD is also an interesting use case that shows how you can deploy a PostgreSQL database as a semi-public service with direct access. A great tool, and a great tool to build other great tools on top of.

12 May 2009

Eddy Petri&#537;or: To the person that almost ran over us

Yesterday, as I was driving towards towards Bucharest, just after exiting Ro iori de Vede, somebody driving a white van with a trailer almost ran over us. I had to drive on the opposite lane to avoid the collision.

During the incident I was cold blooded and managed to keep a clear mind, but right after it, I felt my knees softening and had to stop to recover.

So, in the remote case that person will read this post, thanks for at least breaking when I horned.

11 May 2009

Wouter Verhelst: "Please file a bug!"

I received a few comments on my previous post, some of which suggested that I file a bugreport explaining my thoughts. Of course I did consider that; and I do agree that in many cases, filing a bugreport is the right thing to do. However, this is not always the case. There are times when you just know that a bug which expresses your feelings towards a particular thing will just be closed on sight, or at the very least tagged 'wontfix'. Filing a bugreport in such a case is just not helpful, and a waste of both my time and that of the maintainer. As such, I just don't do it. Instead, what I will do is rant. Not because I want to annoy the world, but because it helps me to blow off steam that's what my blog is for. Also, writing out my thoughts on a particular subject will often help me to reconsider things in such a way that I'll be able to better formulate what the real bug really is; and if it doesn't, it's likely that other people will respond and point me towards what I'm misunderstanding if I am so that, again, I might be able to better formulate what the bug really is. If I sound frustrated in a rant, that's because I am. The simple fact that someone changed something in a piece of technology that I'm using with the intent of improving things should not have to mean that I agree that it is, indeed, an improvement. I will not hide my feelings because it might offend someone. I've done that too much in the past. So please, pretty please, with sugar on top, when I'm ranting, do not tell me to file a bug report. That is all.

10 May 2009

Ana Beatriz Guerrero Lopez: Creating a new GPG key

I wanted to renew my GPG key for some time and after reading the latest news, I finally have generated a new key today.
pub   4096R/6AA15948 2009-05-10
      Key fingerprint = 7A33 ECAA 188B 96F2 7C91  7288 B346 4F89 6AA1 5948
uid                  Ana Beatriz Guerrero L pez <ana@ekaia.org>
uid                  Ana Beatriz Guerrero L pez <ana@debian.org>
sub   4096R/2497B8B2 2009-05-10

Since I tend to forget this stuff, I am blogging all the steps I have followed.
Long and verbose post follows
Update .gnupg/gpg.conf Add at the end of the file:
personal-digest-preferences SHA256
cert-digest-algo SHA256
Create key
ana@pryan:~$ gpg --gen-key
 ...        
Please select what kind of key you want:
   (1) DSA and Elgamal (default)
   (2) DSA (sign only)
   (5) RSA (sign only)
Your selection? 5
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
  
Real name: Ana Beatriz Guerrero L pez
Email address: ana@ekaia.org
Comment:
You are using the  utf-8  character set.
You selected this USER-ID:
     Ana Beatriz Guerrero L pez <ana@ekaia.org> 
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.
   
gpg: key 6AA15948 marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
  
gpg: 3 marginal(s) needed, 1 complete(s) needed, classic trust model
gpg: depth: 0  valid:   3  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 3u
pub   4096R/6AA15948 2009-05-10
      Key fingerprint = 7A33 ECAA 188B 96F2 7C91  7288 B346 4F89 6AA1 5948
uid                  Ana Beatriz Guerrero L pez <ana@ekaia.org>
Note that this key cannot be used for encryption.  You may want to use
the command  edit-key  to generate a subkey for this purpose.
Add other UID
ana@pryan:~$ gpg --edit-key 0x6AA15948
 ...
command> adduid
Real name: Ana Beatriz Guerrero L pez
Email address: ana@debian.org
Comment:
You are using the  utf-8' character set.
You selected this USER-ID:
    "Ana Beatriz Guerrero L pez <ana@debian.org>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a passphrase to unlock the secret key for
user: "Ana Beatriz Guerrero L pez <ana@ekaia.org>"
4096-bit RSA key, ID 6AA15948, created 2009-05-10
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)  Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ unknown] (2). Ana Beatriz Guerrero L pez <ana@debian.org>
Command> save
Change preferences
ana@pryan:~$ gpg --edit-key 0x6AA15948
 ...
Command> showpref
[ultimate] (1). Ana Beatriz Guerrero L pez <ana@debian.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA1, SHA256, RIPEMD160
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@ekaia.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA1, SHA256, RIPEMD160
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Command>  setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
Set preference list to:
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Really update the preferences? (y/N) y
gpg: WARNING: no user ID has been marked as primary.  This command may
              cause a different user ID to become the assumed primary.
You need a passphrase to unlock the secret key for
user:  Ana Beatriz Guerrero L pez <ana@debian.org> 
4096-bit RSA key, ID 6AA15948, created 2009-05-10
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)  Ana Beatriz Guerrero L pez <ana@debian.org>
[ultimate] (2). Ana Beatriz Guerrero L pez <ana@ekaia.org>
Command> showpref
[ultimate] (1)  Ana Beatriz Guerrero L pez <ana@debian.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
[ultimate] (2). Ana Beatriz Guerrero L pez <ana@ekaia.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Command> save
Set primary UID
ana@pryan:~$ gpg --edit-key 0x6AA15948
  ...
Command> uid 1
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)* Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Command> primary
You need a passphrase to unlock the secret key for
user:  Ana Beatriz Guerrero L pez <ana@ekaia.org> 
4096-bit RSA key, ID 6AA15948, created 2009-05-10
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)* Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Command> save
Add subkey for encryption
ana@pryan:~$ gpg --edit-key 0x6AA15948
  ...
Command> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "Ana Beatriz Guerrero L pez <ana@ekaia.org>"
4096-bit RSA key, ID 6AA15948, created 2009-05-10
Please select what kind of key you want:
   (2) DSA (sign only)
   (4) Elgamal (encrypt only)
   (5) RSA (sign only)
   (6) RSA (encrypt only)
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
  
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/2497B8B2  created: 2009-05-10  expires: never       usage: E
[ultimate] (1). Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Command> save
Sign my new key with my old key
ana@pryan:~$ gpg --default-key E8C43461 --sign-key 6AA15948
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/2497B8B2  created: 2009-05-10  expires: never       usage: E
[ultimate] (1). Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Really sign all user IDs? (y/N) y
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
 Primary key fingerprint: 7A33 ECAA 188B 96F2 7C91  7288 B346 4F89 6AA1 5948
     Ana Beatriz Guerrero L pez <ana@ekaia.org>
     Ana Beatriz Guerrero L pez <ana@debian.org>
Are you sure that you want to sign this key with your
key  Ana Beatriz Guerrero L pez <ana@ekaia.org>  (E8C43461)
Really sign? (y/N) y
You need a passphrase to unlock the secret key for
user:  Ana Beatriz Guerrero L pez <ana@ekaia.org> 
1024-bit DSA key, ID E8C43461, created 2004-12-06
  
Send new key to key server
gpg --keyserver pgp.mit.edu --send-key 6AA15948

Ond&#345;ej &#268;ert&iacute;k: My experience with running an opensource project

Nir Aides, the author of the excellent winpdb debugger, sent me the following email on September 21, 2008, so I asked him if I can copy his email and reply in form of a blog post (so that other people can comment and join the discussion) and he agreed. It took me almost a year to reply, but I made it. :)

Hi Ondrej,

How are you?

I am about to publish a new free software project, a new simple PHP framework, and I am interested in your advice.

You started SymPy and were able to make other people join you and develop it with you.
How did you do it?
How did it happen?
Did you actively call for other people or they spontaneously showed interest and joined you?
Are the other major contributor people who were your friends before you started the project?
Did you need to create or manage the project in a particular way to make it attractive to other people?
Are there things you are aware of that promote collaboration or demote it?

I was never successful in doing the same with Winpdb, which while it became reasonably popular, no one has ever joined me to develop it, except for a notable tutorial contribution by Chris Lasher which was developed independently.

Now with the new project, I am wondering what are my chances of making other people try it and take it on. On the one hand it is a new and fresh code base in an interesting field, on the other hand, why would anyone bother to spend their energy on this new project when they have Symfony or Drupal?

What do you think?

BTW, Ohloh believes you have a median of 19,000 lines of changed code per month since the start of their log. Can this be true? Is this humanly possible? According to it SymPy has over 1,000,000 lines of code? I can't understand these numbers. Winpdb has about 25,000 lines after 3 years of development. And from my experience 1,000,000 lines of code projects need about 20-50 full time developers to work on for 2-5 years which is about 40-250 man years. And as if this is not enough you are listed as owner in a dozen other projects in Google code and have enough time to become an awarded scientist. How is this possible?

http://www.ohloh.net/p/sympy/contributors/

BTW2, do you still use Winpdb? If you find yourself using it less, can you say what are the reasons, or what it would take to make it more useful?

BTW3, How is SymPy doing?

Cheers,
Nir



So my most honest answer how to run a successful opensource project is: I don't know.

But nevertheless I tried to summarize some of my ideas and experience and some guidelines that I try to follow, maybe it will be useful to you Nir, or anyone else.

First of all, there has to be a public mailinglist (easily accessible), public bug tracker, nice webpage, easy to find downloads, frequent releases (once a month is good, but in the worst case at least 4 times a year) and a set of guidelines to follow in order to contribute. So that's a must, if the project doesn't have the above, it's almost impossible to become successful. However, that is just a start, just a playground. There are still many projects that have the above and yet they totally fail to attract developers.

So I think the most important principle is that I always think how to employ other people in what I do. If I have some plan in my head how to do something, e.g. how to move some things forward, I always create exact steps and put it to issues, or our mailinglist, so that each step can be done by someone who is completely new to sympy. So I try to look at things from other people's perspective and think -- ok, I quite like this SymPy project and I'd like to get this done (for example a new release, or something fixed, or implemented), but I have no idea how to start and what exactly needs to be done.

So what I try to do if someone comes to our list and asks for something, is that I create a new issue for it and think how I would fix it if I had time. Then write the necessary steps in the issue and invite the submitter to fix it and I offer help with explaining anything and guiding. Now there are two things that can happen. Either the submitter has time and a will to go forward and in this case he starts wrestling with it and whenever he has some code or a question, I need to find time, review it and offer some way out. Or the submitter is too busy, in which case the instructions simply rest in the issues and the next time someone asks for the feature, the instructions are already there. I don't have estimates how frequent either case is.

When I am working on something myself, I try not to code privately, but also put up issues first and put the steps needed in the issues, so that it's easy for other people to join in.

In general, the most precious value for me is the fact that someone else had to sit down at his computer and wrote the patch. So I do everything possible to get new (or more) people interested in the development. Some people think that only super programmers can do a decent job and it's useless to invest time in people that may just have started with Python. They are wrong. Among the SymPy developers (around 65 people total have contributed patches so far at the time of writing this post), we have all kinds of people. We have people from high school, we have a retired US army engineer, we have physicists, mathematicians, biologists, engineers, teachers, or just hobbyists, who do it for fun. Unfortunately, we do not have many women (I think no patch that made it into sympy was contributed by a woman, but I may be wrong), so if anyone has any ideas how to get more women involved, let me know (I know we have several women fans, so that's a good start:). We have people whose first open source project they ever contributed to was sympy and people who are new to Python.

Many times the first patch that a new potential developer submits is not perfect, usually it's faster for me to write it myself, than to help with the first patch, however my rule is to always help the submitter do that. Sometimes he sends a second patch, or a third, and usually it needs less and less work on my side and it already pays off, because he is then able to fix things himself, if he discovers a bug and sympy has just won a one more contributor.

So I came to the conclusion that all that is needed is an enthusiasm. You don't even have to know Python (as you can learn all these things on the way) and you can still do useful things for us and really spare our time.

To answer another question from Nir's email, SymPy has about 130000 lines of code and another about 20000 lines of tests, so I think those stats are wrong. Also the changed lines of code is in my opinion wrong, we usually have about 250 new patches per release (this depends how often we release and other things).

Yes, I am involved in couple other projects, e.g. Debian, Sage, ipython, scipy, hpfem.org (and couple more), basically everything that has to do with numeric simulation and Python, but my activity there varies. The most time consuming thing in the last couple years was definitely school, I was finishing my master in Theoretical Physics in Prague and then moved to the Nevada/Reno and I just finished my first semester here at PhD in Chemical Physics, and sometimes it was just crazy, e.g. I finished teaching at 7pm and instead of going home and sleep, I stayed in my office, fixed 10 sympy issues that were holding off a release, finished at 1am, went home (by bike, since I don't have a car yet), slept couple hours and then did just school again for a week, other people reviewed the issues in the meantime, and then I made the release (instead of sleeping again). In the last semester it was not unusual that I got home at 1am every week day, then slept most of Saturday to catch up, on Sunday I did some laundry and shopping, and the rest of time I did grading and homeworks for all my classes and teaching, no time for anything else (e.g. no friends, no girls, no rest, no hobby, no opensource stuff, nothing). So sometimes one has to work pretty hard to get through it, but fortunately it's behind me finally, if all goes well, I should be just doing research from now on and have a real life too. Also I am sorry I didn't manage to reply sooner. :)

To answer the other questions:
Are the other major contributor people who were your friends before you started the project?
No, not a single major contributor was my friend before I started the project. Every single one of them become a developer using the procedure I described above, e.g. first showed on the list or in the issues, and maybe even the very first patch was not a high quality one (and if I was stupid and arrogant, or didn't see the big potential, I would just ignore them). But when given a chance, they became extremely good developers and sympy would simply just not be here without them.

Did you actively call for other people or they spontaneously showed interest and joined you?
I very much encourage everyone to contribute, but the initial interest must be in them, e.g. they at least have to show around the mailinglist/issues, so that I know about them. But once I know they are interested in some issue, yes, I try to invite them to fix it, with my help.

One observation I made is that I have to always think in the spirit "how to earn new money, not how to spare the money I already have", e.g. when applied to sympy, how to get new developers, how to develop the new great things etc. Even if I am super busy as I was, I still have to think this way. Once I start thinking how to conserve and preserve what we already have, I am done, finished and that's the road to hell.

If I am open, positive, full of energy, I can see people joining me and we can do great things together. It probably sounds obvious, but it was not for me, when for example some people I worked with, started their own projects, when I got busy, and started to compete, instead of helping sympy out. And I felt betrayed, after so much work that I invested into it and started to become protective. And then I realised that's wrong. I can never stop other people do what they want to do. If they want to have their own project, they will have it. If they don't want to help sympy out, they won't (and what is more important, there is nothing wrong with either of that). It's that simple and being protective only makes things worse.

There is also a question of the license that you use for the project, e.g. one should basically only choose between BSD (maybe also MIT or Apache), LGPL and GPL (there are also several versions of the GPL licenses). Unfortunately the fact is, that there are people who will never contribute a code under a permissive BSD license (because it's not protecting their work enough) and there are also other people who really want to code to be BSD (or other permissive license) so they can sell it and they don't need to consult with lawyers what they are or aren't allowed to do and also so that they can combine it with any other code (opensource or not). It also depends if one wants to combine (and distribute) other codes together. So choosing a license is also important. I believe that for sympy BSD is the best and for other projects (like Sage) GPL is the best and one has to decide on a case by case basis. For Winpdb, I would make it BSD too, since you can get more people using it.

To conclude, SymPy is a little more than 2 years old, and it has been a great ride so far and more things are coming, e.g. this summer we have 5 Google Summer of Code students and people are starting it to use in their research and we plan to use it in our codes at our group here in Reno too, so things look promising. I am really glad, we managed to build such a community, so that when I am busy, as I was the last semester, other people help out with patches, reviews and other things, so that the project doesn't stall and when I got rid of my school duties now, we can move things forward a lot.

So maybe you can get inspired by some of the ideas above. I am also interested in any discussion about this (feel free to post a comment below, or send me an email, or just write to a sympy list about what you think).

9 May 2009

Biella Coleman: Fresh

If you are into sustainable farming this movie will likely catch your fancy.There is a screening here in NYC at the end of May. Supposedly they are going to stream the movie online, which I certainly hope to be the case. A political documentary that is behind bars is really not so useful and is a contradictory project as well. If you are into the idea of farming but live in the city, and New York City in specific, you can attend a Htink workshop on May 17th and start urban farming.

Biella Coleman: Fresh

If you are into sustainable farming this movie will likely catch your fancy.There is a screening here in NYC at the end of May. Supposedly they are going to stream the movie online, which I certainly hope to be the case. A political documentary that is behind bars is really not so useful and is a contradictory project as well. If you are into the idea of farming but live in the city, and New York City in specific, you can attend a Htink workshop on May 17th and start urban farming.

8 May 2009

Alastair McKinstry: Funding Public Health care : the bigger picture

Adrian von Bidder raises an interesting discussion on why public health care is difficult. Basically, it comes back to the challenge:
How much money should be spent on this person's illness? which is a very, very bad question. We try to sidestep it by only taking about statistics etc., but no matter how you look at it, you either do 20'000  per week medications for 80 year old patients who will die soon anyway and get a system society can't pay, or you don't and you get a system where the rich are better off than the poor.
The problem is, the majority of health costs are in the last few years of a persons life: when the body is breaking down. If viewed from the problem of health-care funding vs. eg. education, you have an ethical dilemma: is it worth it ? Here there are no easy answers. Nick Bostrom wrote a very interesting and persuasive essay a while back, The fable of the Dragon Tyrant. In short, we are getting somewhere with regenerative medicine While cures are hard to come by at this stage, there is a growing realization in medicine that senesence, what we used to call "old age", is curable. But we have a lot of psychological defensive mechanisms to help us cope with the carnage of old age that make us deny the problem: if we look afresh at "old age" knowing it to be curable, any delay in doing so is abhorrent. From a public, societal perspective, we spend a fortune every year on health. But we do so in a very disjointed way: we pay colossal amounts for health care, but also for basic health science: in the US, for example, the budget for the National Institutes of Health is about 30 billion dollars. Nearly twice that of NASA. Similar figures are spent in Europe, but there is this strange gap in the middle: the drug companies and medical industry. We start the development of new drugs with public money, and we buy the drugs with public money, but the choice of what drugs and treatments are developed are left to private industry, that is, a profit motive. This results in many cases in expensive treatments to treat symptoms rather than necessarily cure the problem. Faced with the huge costs of geriatric medicine and senesence, the response should be co-ordinated: funding a cure will be expensive, but save a fortune (Think, instead of a pensioner slowly dying and 'being a drain on resources', of 'experienced citizen in the prime of their productive, tax-paying years'). Instead of funding the basic science alone, we should be funding the complete drug and treatment development publically, only farming out the actual manufacture to private industry. It is silly to spend a fortune to keep merely keep someone alive at the age of eighty or so, when we know for a larger investment (bigger than a private company can do), we can cure them properly. The solution to the dilemma, then, is to stop thinking of the elderly being a drain, but actually applying our public efforts in a co-ordinated manner to solving the carnage of old age. Tags ,

7 May 2009

Biella Coleman: Make our words glisten



glisten vs hardened words, originally uploaded by the biella.
Now that I am (thankfully) done teaching until September, I have time to devour two small mountains of readings that I need to finish before I return to my manuscript, which I will be working on, I hope uber-productively, all summer long. One pile of readings deals with coding, open source, and the commons, such as Scott Rosenberg s Dreaming in Code and David Bollier s Viral Spiral. Another pile of reading edges toward the theoretical side of things, having to do with craft, pleasure, and humor, since it is pleasure in its many many many guises from from the calm feeling of self-satisfaction that underlies pride in one s craft, to the more sublime feeling of ecstatic bliss that powers many creative sprints. If one entertains pleasure, one must also entertain its darker side, for all of this feel good stuff is nonetheless often springs forth from a deep sea of passionate frustration. This seems to be the driving theme of Dreaming in Code and it is also what animates Ellen Ullman s fictional account of pure frustration, The Bug. I am quite fond of native expressions of geek frustration and recently was provided with an exquisite example a rant against the Adobe PSD format. The author of Xee, A light-weight, fast and convenient image viewer for Mac OS X explained his utter contempt for the Adobe PSD in the following way:
At this point, I d like to take a moment to speak to you about the Adobe PSD format. PSD is not a good format. PSD is not even a bad format. Calling it such would be an insult to other bad formats, such as PCX or JPEG. No, PSD is an abysmal format. Having worked on this code for several weeks now, my hate for PSD has grown to a raging fire that burns with the fierce passion of a million suns. If there are two different ways of doing something, PSD will do both, in different places. It will then make up three more ways no sane human would think of, and do those too. PSD makes inconsistency an art form. Why, for instance, did it suddenly decide that *these* particular chunks should be aligned to four bytes, and that this alignement should *not* be included in the size? Other chunks in other places are either unaligned, or aligned with the alignment included in the size. Here, though, it is not included. Were it within my power, I would gather every single copy of those specs, and launch them on a spaceship directly into the sun.
Even if this account represents unadulterated irritation, he leaves us, the reader, with nothing of the irritation, only pleasure. This aftermath of frustration is delivered through the vehicle of humor, which within the hacker context, is the cultural container that best captures the spirit of hacker pleasure or so I will be arguing. Like many humorous rants from the world of hacking (and please send me any others you know of), this text dances with liveliness; it exudes its own rhythm; it glistens to use Ronald Barthes apt phrasing from his short book The Pleasure of Text, which I just finished as part of my theoretical escape into the pleasure-dome. Although there are parts of his book which are to be frank, *really* *not* *pleasurable*, partly due to obscure references to High French Theory, which elide even an academic pair of eyes, the book generally pleases. And one of the most pleasing chunks is his definition of a stereotype:
The stereotype is the word repeated without any magic, any enthusiasm, as though it were natural, as though by some miracle this recurring words were adequate on each occasion for different reasons, as though to imitate could no longer be sensed as an imitation: an unconstrained word that claims consistency and is unaware of its own insistence
In contrast to the stereotype, a string of words that enchants does so by slipping off the page to hit you squarely in the heart or the gut. Unfortunately, while academic writing steers clear of stereotypes, often trying to present the detailed singularity of a phenomena (even when conditioned by social forces), it does not exactly glisten, though there are a handful of exceptions. I think we need more texts that glisten, even if only during sections or parts of our books and articles (much like the rant helped enliven the more staid technical document). In recent years, in large part due to the influence of free software, there has been an explosion, a move toward going open access. All of this is laudable and I fully embrace it (and have gotten into some small battles over it). But without an aesthetic politics that values pleasure in reading and writing we are doomed to obscurity anyway. A move toward making our knowledge public also required a move toward thinking about the literary aesthetics of pleasure.

Biella Coleman: Make our words glisten



glisten vs hardened words, originally uploaded by the biella.
Now that I am (thankfully) done teaching until September, I have time to devour two small mountains of readings that I need to finish before I return to my manuscript, which I will be working on, I hope uber-productively, all summer long. One pile of readings deals with coding, open source, and the commons, such as Scott Rosenberg s Dreaming in Code and David Bollier s Viral Spiral. Another pile of reading edges toward the theoretical side of things, having to do with craft, pleasure, and humor, since it is pleasure in its many many many guises from from the calm feeling of self-satisfaction that underlies pride in one s craft, to the more sublime feeling of ecstatic bliss that powers many creative sprints. If one entertains pleasure, one must also entertain its darker side, for all of this feel good stuff is nonetheless often springs forth from a deep sea of passionate frustration. This seems to be the driving theme of Dreaming in Code and it is also what animates Ellen Ullman s fictional account of pure frustration, The Bug. I am quite fond of native expressions of geek frustration and recently was provided with an exquisite example a rant against the Adobe PSD format. The author of Xee, A light-weight, fast and convenient image viewer for Mac OS X explained his utter contempt for the Adobe PSD in the following way:
At this point, I d like to take a moment to speak to you about the Adobe PSD format. PSD is not a good format. PSD is not even a bad format. Calling it such would be an insult to other bad formats, such as PCX or JPEG. No, PSD is an abysmal format. Having worked on this code for several weeks now, my hate for PSD has grown to a raging fire that burns with the fierce passion of a million suns. If there are two different ways of doing something, PSD will do both, in different places. It will then make up three more ways no sane human would think of, and do those too. PSD makes inconsistency an art form. Why, for instance, did it suddenly decide that *these* particular chunks should be aligned to four bytes, and that this alignement should *not* be included in the size? Other chunks in other places are either unaligned, or aligned with the alignment included in the size. Here, though, it is not included. Were it within my power, I would gather every single copy of those specs, and launch them on a spaceship directly into the sun.
Even if this account represents unadulterated irritation, he leaves us, the reader, with nothing of the irritation, only pleasure. This aftermath of frustration is delivered through the vehicle of humor, which within the hacker context, is the cultural container that best captures the spirit of hacker pleasure or so I will be arguing. Like many humorous rants from the world of hacking (and please send me any others you know of), this text dances with liveliness; it exudes its own rhythm; it glistens to use Ronald Barthes apt phrasing from his short book The Pleasure of Text, which I just finished as part of my theoretical escape into the pleasure-dome. Although there are parts of his book which are to be frank, *really* *not* *pleasurable*, partly due to obscure references to High French Theory, which elide even an academic pair of eyes, the book generally pleases. And one of the most pleasing chunks is his definition of a stereotype:
The stereotype is the word repeated without any magic, any enthusiasm, as though it were natural, as though by some miracle this recurring words were adequate on each occasion for different reasons, as though to imitate could no longer be sensed as an imitation: an unconstrained word that claims consistency and is unaware of its own insistence
In contrast to the stereotype, a string of words that enchants does so by slipping off the page to hit you squarely in the heart or the gut. Unfortunately, while academic writing steers clear of stereotypes, often trying to present the detailed singularity of a phenomena (even when conditioned by social forces), it does not exactly glisten, though there are a handful of exceptions. I think we need more texts that glisten, even if only during sections or parts of our books and articles (much like the rant helped enliven the more staid technical document). In recent years, in large part due to the influence of free software, there has been an explosion, a move toward going open access. All of this is laudable and I fully embrace it (and have gotten into some small battles over it). But without an aesthetic politics that values pleasure in reading and writing we are doomed to obscurity anyway. A move toward making our knowledge public also required a move toward thinking about the literary aesthetics of pleasure.

Biella Coleman: Not Crazy Just Nuts

So I am sipping some hot chocolate made from a recently purchased cream substitute by the name of Mimiccreme. Honestly, the stuff tastes good and better, it froths, unlike most non-dairy substitutes. Yet there is a hitch (there always is). As I was whisking away at my cream (mixed with water), I was staring blankly at the box and noticed that they have applied for a patent, which is indeed the case. Since their formula is made out of nuts, their motto is Not Crazy Just Nuts and if they are granted the patent (though I am confused as to what they are trying to patent) it will be Nuts and Crazy as well. update: Ettienne pointed us in the comments to the the patent application

Adrian von Bidder: Why Public Health-Care is Difficult

A reply to Tore, who is probably partly wrong. I don't claim the U.S. system is good or bad, I don't know it. But I don't think public (which he seems to imply means free) health care is as easy as he suggests. I'm starting at his assertion that
Very few people break their legs intentionally to stay at a nice hospital. [Health care] is not a resource likely to be wasted once people are given free access to it.
The case of a broken leg is easy. What about chronic illnesses, especially those difficult to diagnose (some kinds of back pain, psychological problems, ...)? What about bored old people who spend their days talking to doctors about how bad getting older is? Easily available (cheap or free) health care has lead to hospitals being swamped with people with minor issues to the point where people with serious problems died because hospital staff didn't get to them in time. And, because the state's budget is not infinite, hospitals become badly run institutions with always-overworked staff leading to even fewer people wanting to work there etc. This has happened in the UK, for example (I think the system I have been reading about ages ago has since been replaced by a different one.) Switzerland doesn't have this problem (to this extent) because we really care about (this means, here: throw money at) our health system, but the result is that the mandatory health insurance becomes insanely expensive. There is talk about half the population needing state subsidies to pay for their health insurance within the next few years. Which, of course, will just move the cost from the whole population (via mandatory health insurance) to the whole population (via taxes) so I don't quite see the point... You'll note I don't propose solutions either. But I think it's important to acknowledge that health care is a difficult topic because, in the end, it always comes down to the question How much money should be spent on this person's illness? which is a very, very bad question. We try to sidestep it by only taking about statistics etc., but no matter how you look at it, you either do 20'000 per week medications for 80 year old patients who will die soon anyway and get a system society can't pay, or you don't and you get a system where the rich are better off than the poor. Or you delegate the decision to the doctor or the insurance or ... and try to minimize the number of people who deserve (can you see it, the hard question didn't get away!) treatment but don't get it. Update 20090508 - Response to comments I'd like to thank you for commenting. I didn't know (and sorry about that didn't care to research) that the U.S. system is even more expensive than ours, since my main message is just that health care is about hard decisions. Some people always will be left out. Elaborating a bit on the 20'000 a week medication: partly, I agree with Adrian and Tore: patent-supported monopolies on medication plays a part. Partly, because I stipulate there will always be rare illnesses where a few cases per year worldwide will have to pay for all the research and production of the medication. Of course, the cost can be distributed so that the patient (or his insurance) doesn't have to pay it, but society as a whole will still pay. So the hard question won't go away easily, now it's just become Do we fund research for this rare illness with fewer than five cases per year worldwide? Of course, now we're not speaking of people anymore, but already just of cases, and we're not cutting treatment for an actual person but we're just cutting budget on research, so it may be easier on the conscience, but it's still fundamentally the same question. Conclusion? Health-care will always be a difficult topic, and it will never be free. The cost can just be distributed in different ways.

5 May 2009

Manoj Srivastava: Manoj: Debian list spam reporting the Gnus way

So, recently our email overlords graciously provided means for us minions to help them in their toils and help clean up the spammish clutter in the mailing lists by helping report the spam. And the provided us with a dead simple means of reporting such spam to them. Now, us folks who knoweth that there is but one editor, the true editor, and its, err, proponent is RMS, use Gnus to follow the emacs mailing lists, either directly, or through gmane. There are plenty of examples out there showing how to automate reporting spam to gmane, so I won t bore y all with the details. Here I only show how one serves our list overlords, and smite the spam at the same time. Some background, from the Gnus info page. I ll try to keep it brief. There is far more functionality present if you read the documentation, but you can see that for yourself.
The Spam package provides Gnus with a centralized mechanism for detecting and filtering spam. It filters new mail, and processes messages according to whether they are spam or ham. There are two contact points between the Spam package and the rest of Gnus: checking new mail for spam, and leaving a group. Checking new mail for spam is done in one of two ways: while splitting incoming mail, or when you enter a group. Identifying spam messages is only half of the Spam package s job. The second half comes into play whenever you exit a group buffer. At this point, the Spam package does several things: it can add the contents of the ham or spam message to the dictionary of the filtering software, and it can report mail to various places using different protocols.
All this is very plugin and modular. The advantage is, that you can use various plugin front ends to identify spam and ham, or mark messages as you go through a group, and when you exit the group, spam is reported, ham and spam messages are copied to special destinations for future training of your filter. Since you inspect the marks put into the group buffer as you read the messages, there is a human involved in the processing, but as much as possible can be automated away. Do read the info page on the Spam package in Gnus, it is edifying. Anyway, here is a snippet from my etc/emacs/news/gnusrc.el file, which can help automate the tedium of reporting spam. This is perhaps more like how Gnus does things than having to press a special key for every spam, and which does nothing to help train your filter.
    1  (add-to-list
    2   'gnus-parameters
    3   '("^nnml:\\(debian-.*\\)$"
    4           (to-address . "\\1@lists.debian.org")
    5           (to-list . "\\1@lists.debian.org")
    6           (admin-address . "\\1-request@lists.debian.org")
    7           (spam-autodetect . t)
    8           (spam-autodetect-methods spam-use-gmane-xref spam-use-hashcash spam-use-BBDB)
    9           (spam-process '(spam spam-use-resend))
   10           (spam-report-resend-to . "report-listspam@lists.debian.org")
   11           (subscribed . t)
   12           (total-expire . t)
   13           ))

Andrew Pollock: [tech] Analog cable's days numbered?

Apparently Comcast is planning on axing its analog cables at some undetermined point in the future. That will make my MythTV setup more complicated, and no doubt require a more expensive cable plan and yet more equipment. My setup is already a tad ridiculous.

4 May 2009

Eugene V. Lyubimkin: cupt: let me introduce it

Cupt is experimental re-implementation of APT suite from scratch using Perl .
It consists of Perl modules and console front-end to them.

Why?

- to finally avoid some bugs in APT design;
- to introduce some useful features;
- to make an extensible and readable codebase;


What infrastructure does Cupt use?

It uses the same APT infrastructure, e.g. index files, deb cache archive
files, configuration files. It understands some of widely used APT options.


What useful features has Cupt already?

- full-case strict dependency problem resolver;
- command-line and APT-like option name checker;
- case-sensitive search;
- pinning by source package name;
- pinning by package groups using shell-like patterns;
- configurable 'depends' and 'rdepends' subcommands;
- 'satisfy' subcommand.

What features will Cupt have in future?

See incomplete roadmap.


Why is it 'experimental'?

Because not all important functionality is implemented yet:
- 'update' action;
- cooperating with debconf;
- working with source packages;
- translated package descriptions;


Why Perl?

- I like Perl
- code conciseness
- code extensibility
- several useful libraries available


Can I use Cupt along with APT?

Yes, you can mix apt-get/apt-cache/aptitude/etc. with cupt without bad consequences.


Can I build a Debian package for Cupt?

Yes, go to repository, checkout it and build the Debian package as usual.


What's the status of Cupt in Debian?

It's currently in the NEW queue, but don't rush to try root-required actions because it's still experimental.


Who am I?

The man who had been contributing to the APT.

Steve Kemp: A lot of people drink mineral water

dmonitor now has a webpage. I've been running it for a night now, watching alerts come and go via manual firewall rules so I'm pretty confident it works reliably and in a way that avoids transient failures. The only obvious failure case is if each monitoring node loses the links to each of the others. (Solution there is to have a sufficiently large number of them! Hence the reason the configuration is file/directory based. rsync for the win!) Still I will leave it there for now. The only things missing are better instructions, and more service checking plugins.. Now to go paint some more ... adding new wall decorations has inspired me a little! ObFilm: Heathers

2 May 2009

Jeff Bailey: Mother's day

I subscribe to the iRobot mailing list for new products, discounts, etc. Today I got an email talking about great deals for mother's day. In case of you out there think this is a good idea, let's state this clearly:

This is not a good idea.

Giving someone a gift that reminds them of housework is a fast path to tears. Even if they're a geek. Just say no.



Next.

Previous.