20101124

Growing Delphi code

I find Delphi as a language has its perks but doesn't come without annoyances. I'm not so much comparing it to other programming languages here (i would not know where to start), but take a look at how to not waste time or make bad code when you ARE using Delphi. This article is no less relevant if you use other languages though.

Its all about designing pillars, reusing them, and being able to replace them one by one with improved versions after the facts.
An application must be able to grow as its maintained, one pillar at a time.

Re-usability.
Everybody knows you must document your code, order and version your source files, have a code standard so i won't go into the obvious here concerning re-usability. But what do i mean when i say re-usability:
"The ability of a package or subprogram to be used again without modification as a building block in a different program from the one it was originally written for."
In dutch i often call this "draagbare code" aka portable code. Take it with you, plug it in, it should work without requiring even more code.

Package is the key word here, its what Delphi likes doing. Or moreover, it should be what you like doing. Delphi enables you to make packages of code, useful when you want to compile a DLL, when you develop a custom component. I presume its also useful as a library of code, but this Delphi has yet to prove me. It seems projects using a package lack full debug capabilities. This is because they only access the DCU file, not the PAS. I imagine this DCU file can be circumvented by compiling projects (or packages) another way (non-linked?), but i  am not sure yet. If you know of a way, please post it in the comments.

Do not cast your Delphi code into concrete. When building writing a unit that should be reusable, make sure not to:


  • Put your attributes and functions in the private section of your class. Your solution is a quick hack anyway, so it's better to hide it.
  • Don't declare a procedure of function virtual. Really, no one wants to override what you did anyway.
  • Use enumerated types. No one ever will have a need to extend this type.
  • Write procedures and functions in the implementation of your unit, and don't export them. They're not good enough to be reused anyway.
These are just the tip of the iceberg. Avoiding this may save you (and your coworkers) a headache.



Versioning shared units.
At time of writing (2010) Delphi RAD still lacks a version control solution i find decent. I now use Git, which doesn't integrate at all. This is difficult when files are used by more than one project. Using packages in Delphi gets you halfway, but not far enough. Consider this common scenario:

  • A unit "U" that implements function "F" returning a type "T".
  • A custom component "C" that when put on a form has a GUI to let the user use "F" from "U", thus returning "T".
  • A custom component "D" that when put on a form has a GUI to let the user see "T".
  • A project with a form that contains "C" and "D", and must know of "T" in order to have "D" display what "C" did.
  • Another project, using "T". Thus requiring "U".
  • Another component, using "T". Thus requiring "U".

On the last two lines I say "requiring" as if these should know about the PAS file. This is what i prefer, but it just about impossible to do with Delphi without making the source-file references that clutter your projects look like chaos. The reason i prefer this above DCU files, is because these don't enable me to debug their code.

But the real reason i put forward this scenario is to show you what problems arise when you try to do this in a controlled manner, using version control. How i imagine this should be done:

  • Develop unit "U" in a repository, once in a while spawning a stable branch.
  • Develop package (storing "C" and "D") in a repository, once in a while spawning a stable branch. When it spots a newer stable branch of "U" at compile, it informs me clearly and pulls it.
  • Develop project in a repository, once in a while spawning a stable branch.
Problem however is that Delphi is a jerk here and requires access to BPL, DCU, and PAS files. I've yet to figure out a way of arranging this so everything "just" works.


Folder structure as a remedy
I've tried lost of folder structures over the last few days, and regret having to resort to my initial setup.
I tried a huge repository containing all components and shared code (as a library package), and found it difficult to find a place for each components' test-project. Ultimately this structure was clear but Delphi still was a jerk about files it required in its search path.

Right now, i'm considering compiling all DCU files to a central folder like "\lib\" but still struggle with where to put that folder. I believe that code should be kept together, and as such that DCU's (except for the VCL and RTL lib ofcourse) in my program files folder should have no place in my application. I want to be able to just open the same code on a different computer and be able to compile everything exactly as it was before.

There's lots of resources on what folder structure a Delphi project could be kept in, so to add on those here is an attempt to share my way of structuring this.

  • / - The root of this package or project. Contains my DPROJ file, RES file, and such.
  • /generated/ - contains everything Delphi makes up from my code. (and contains dcu, bpl, bin folders)
  • /src/ - contains my source code.

I always put a testproject alongside a package, and have a ProjectGroup assigned to both DPROJ files to easily open it as a whole. The whole shebang is then saved in some form of version control.

(Disclaimer: to my liking this article is far from finished, but i decided to publish it anyway whilst i'm diving further in this matter. Contributing comments will be amended.)

References:

20100615

Force Android to use the faster WCDMA data connection.

I've experienced a slow internet uplink lately, and some of this is being taken care of by T-Mobile Netherlands as we speak. Today i received word that i could do something about this myself, as well.

There is a setting in my Google G1 (Android v1.6) phone that forces the phone to only connect with the faster WCDMA networks, and to not degrade or negotiate this. This means my geographical coverage will not improve or -more probably- get worse as there are places plenty that don't offer WCDMA at all, but i'm willing to give this a try.


From the dialer, type exactly:
*#*#4636#*#*
After a moment, a screen will appear called "Testing". Select the drop-down that says "Phone Information". From there, scroll down to where it should say "WCDMA preferred", and change it to "WCDMA only". Use the back key to get out. It should stay selected even through a reboot.
  
This menu contains a host of test buttons and statistics on connections and phone usage. I'll update this article if and when i gain new insights on this.

20100207

BTTF: I hate manure

This is a compilation of manure moments on the hit Back To The Future movies. A lot of key moments in BTTF feature actors familiar from previous installments; characters like Biff, the clocktower guy, the `What are you, chicken?` guy (Needles), and the manure cart has a recurring role.

The manure company is run by the family Jones. First there was D. Jones `Manure Hauling´ in BTTF1:
Then there was D. Jones again, in the second installment.

And finaly in BTTF3 you see A. Jones in the wild west:
In the beginning of this movie, even Marty looks surprised to find them everywhere. Actually .. it would not surprise me to even find the same actor alongside the cart each movie.
Thats a nice touch. I really like BTTF and would love to see more. If they would make any more movies tho, they would sure ruin that.

Lets just hope more movies of this niche are in the pipeline in the 20th century. A good comedy is a smart movie.

There´s also a big list of goofs on this movie at IMDB: http://www.imdb.com/title/tt0088763/goofs
Ever noticed this creepy kid at the end of BTTF3? http://www.youtube.com/watch?v=zq5-6PkVGCg

PS - i realize most fans of this people already noticed this detail. This page is those who appreciate it, and those who did not realize. Yet. (shame on you)

20091204

DNS forgery by UPC

I made a typo when connecting a fresly installed Filezilla client to my domain at staesit.nl

This is what the Filezilla log said:
Status: Resolving domain staesit.nll
Status: Connecting with 67.63.50.51:21...
The TLD nll doesn't even exist! Oh crap whats this?

How then does filezilla end up with to this IP? Hostname of said IP resolves as:
upcnlassist-c.infospace.com
Aha! My (one week lived) provider UPC.nl is in on it.

My provider is doing something i don't want it to. Seems like it assumes identity of staesit.nll. Stuff like this just makes me mad and sad at the same time. :( DNS forgery should be banned.

I won´t even start on the searchpage that now pops up on misspelled domains.. wait. Actually i will exactly that as it seems like this is actually causing said behavior.

> ping zoek.upc.nl
Pinging assist.infospace.com [67.63.50.57] with 32 bytes of data:
Reply from 67.63.50.57: bytes=32 time=98ms TTL=243

20091124

Archive backup periodicly

I'm not into typing much about such simple subjects, but i just had to share this old batch code. Turns out there is no quick and neat solution available for moving your daily backups to separate folders. So in short and without further adieu;

Backups are important. All Staes IT web servers submit backups on a regular basis to secure offsite locations. These should run automated and reliable, without much human intervention.

Problem
These backup server receives backups via FTP each day. I don't want the next day's backup to overwrite the current ones, so have to archive them in a daily manner. It also looks nice when browsing the backups folder. Keeps everything nice and organized.

I should run a script every morning to archive those nightly backups to do the job for me.

Solution
This scripts puts all files a folder named "bu_YYYYMMDD_auto". Run this daily when the ftp backups are finished.

Since i've realized this script over 7 years ago people keep asking me how to do such a thing with batch files. So i figured i should just put it on the internet for all to see. Sorry for the delay, i only recently started this blog thing.

Back then i created two batch files to suit my needs at the time. One named "bu_shift.bat" checks if files exist with the correct extention, then creates a folder using the date, and moves all files in here. It outputs the results to the console. The other file named "bu_shift_keeplog.bat" just calls the above and puts the results in a daily logfile. Files are listed below.

It assumes the incomming files are at ./bu_ftp_up/*.gz and you could easily change that yourself.

Also keep in mind better solutions exist. This one will work out of the box and simply does its job - thats the only reason i present it here.

bu_shift.bat
@echo off

REM Run this file as a cronjob, some time after the FTP has delivered a backup.
REM All folders are appended with _auto to easily distinguish them from manual backups.

echo.
echo ****************************************************
echo * Start backup shift:
echo.
if not exist ".\bu_ftp_up\*.gz" GOTO NoFiles


for /F "tokens=2-4 delims=/- " %%A in ('date/T') do set var=%%C%%B%%A

echo * Creating folder bu_%var%_auto:
md "bu_%var%_auto"
echo.
echo * Moving files to folder:
move ".\bu_ftp_up\*.*" ".\bu_%var%_auto\"
echo.
GOTO End


:NoFiles
echo * Stopped: found no files in "bu_ftp_up".
echo.


:End
echo * End of batch
echo ****************************************************
echo.
Above neatly outputs results in the console.
When running this as a cronjob use below file to log this to aptly named files.

bu_shift_keeplog.bat
@echo off
for /F "tokens=2-4 delims=/- " %%A in ('date/T') do set logd=%%C%%B

set logfile=bu_shift_log_%logd%.txt

echo. >> %logfile%
echo bu_shift_keeplog.bat op %date%, om %time% >> %logfile%
.\bu_shift.bat >> %logfile%
echo. >> %logfile%
In Windows you can add this file as a cronjob via "Task Scheduler". This code has been in use for over five years on various Windows Server 2003 and 2008 environments, and continues to serve a purpose. Happy sharing!

PS - boy this Blogger editor is worth shit. Awfull code markup.