Install GExperts. You may never use anything but their grep, but for that alone, it's worth it: fast, flexible, and a great UI for viewing the search results. It's a pity their regular expression support sucks so bad.
Always make your constructor's first line be "inherited Create(...)" and your destructor's last line be "inherited Destroy;". Don't try to get tricky and do things before inherited Create, or (worse yet) after inherited Destroy; it will bite you sooner or later. Call the inherited constructor/destructor even if you're descending from TObject and the inherited call isn't technically necessary. You may refactor later, and not be descending directly from TObject anymore, and wondering why you have memory leaks.
When you're trying to decide whether something should be a function or a read-only property, ask yourself, "Is this something I would want to hover over in the debugger and see its value?" If so, it's worth the extra overhead to make it a property.
Learn to use the full-debug-mode version of the FastMM memory manager.
Understand that Free and FreeAndNil do nil checks for you. You don't need to write "if Something <> nil then FreeAndNil(Something)"; just call FreeAndNil.
Write your destructors defensively. In particular, don't assume that all your fields have been initialized, even if they're all initialized in the constructor. If an exception got thrown during the constructor, then the destructor will run immediately, and some of your fields might still be nil. If your destructor throws an access violation, you just lost out on finding out what the original error was.
Never optimize unless you've proven you know where the bottleneck is. (Not Delphi-specific, but relevant given some of others' tips about making parameters const and the like.)
In keeping with the previous point, never mark an interface-type parameter as "const" unless you really, really know you need to, with the profile results to back it up. It's too easy (and perfectly reasonable!) to write code that calls MyMethod(TMyInterfacedObject.Create). If MyMethod's parameter was marked as const, you just leaked an instance of TMyInterfacedObject -- the const parameter tells the compiler "don't bother calling _AddRef and _Release", so the object never got freed.
Avoid parallel indexed properties (e.g. a Strings[] property and an Objects[] property where Strings[3] logically corresponds to Objects[3]). Instead, make one indexed property that contains an object with multiple properties. Centralizes your logic and makes the code cleaner in the long run.
Don't use primitive data types if they don't fit. Make your own custom data types using records with methods. For example, if you keep needing to operate on a month-and-year (but don't care about the day), don't try to pass a pair of integers all over the place, or a TDateTime with a day that you try to ignore. Make a TMonthAndYear instead. Give it constructors and/or factory methods. Give it properties. Overload the = operator. Add an overloaded CheckEquals to your base DUnit test case that can compare two TMonthAndYears. You'll be amazed at how much clearer your logic becomes.
Last but not least: I know there are those who would rather be programming in assembly than in Delphi, would rather write their own memory manager than use FastMM, cringe in terror at the very mention of garbage collection, and who will therefore flame me endlessly for this, but our shop's #1 Delphi tip, arrived at through years of experience, is: Unless you have a good reason not to, interface everything. Don't waste brain cycles thinking about memory management; it is not worth it. Perhaps 0.5% of our interfaces have become performance problems, and (with profile results) we've been able to address those. And they make coding so much easier. Make a function that returns an interface instead of populating half a dozen out parameters, and use that result all you want but never have to free it. Get rid of the inevitable try .. finally .. FreeAndNil, and those endless chains of FreeAndNils in your destructors (did you remember them all?). Pass an object around with confidence that it'll get cleaned up when the last person is done with it. And curse the Delphi developers for forcing you to choose between code that's easy to browse through and code that's easy to maintain.