Friday, December 03, 2004

More on Inline in Delphi

Turns out Remco is the person I have been exchanging with about the inline warnings. He isn't too thrilled that he needs to use the {$IFDEF WINDOWS} directive. That is understandable. Most developers dislike the dreaded IfDef compiler directive.

What else can he do? Especially with his "do not use not used units" policy?

You have two other options to get rid of this warning without adding Windows to the uses clause (even though it is already included in your compiled application because you use SysUtils that uses Windows). What the warning is telling you is that although you (or another developer) specified that the function should be inlined, but because of your uses clause it cannot.

You can just tell the compiler to turn of inlining all together with the {$INLINE OFF} compiler directive. This ignores all those Inline directives on your functions. Remove all benefit and annoyance of this new feature.

The other option is the {$INLINE AUTO} compiler directive. This tells the compiler that you trust it to inline functions based completely on its judgment. This also ignores the Inline directives on your functions, but instead of disabling Inlining the compiler just makes all the decisions on its own. Interestingly, if I don't have a carriage return between $INLINE and AUTO then the error insight and Structure panel flags it as an Invalid compiler directive, but it compiles fine. Adding a carriage return fixes it.

Either directive removes the hint about not having the correct unit in your uses clause. {$INLINE ON}is the default compiler directive. This compiler directive is site specific. In other words you would need to added it to the top of each unit you want to change the behavior in. Alternatively you could just surround the procedure that makes the inline call in question with OFF and ON directives. Don't know if that is better then IfDef though.

Wednesday, December 01, 2004

Delphi Inline functions and your Uses clause

Back on More Coding Peeves someone asked me about the warning:

'AnsiSameText' has not been expanded because unit 'Windows' is not specified in USES list
I looked in SysUtils and AnsiSameText is declared as:
function AnsiSameText(const S1, S2: string): Boolean; inline;

So it is in fact an Inline function. The help for the warning explains:

This situation may occur if an inline function refers to a type in a unit that is not explicitly used by the function's unit. For example, this may happen if the function uses inherited to refer to methods inherited from a distant ancestor, and that ancestor's unit is not explicitly specified in the uses list of the function's unit.

If the inline function's code is to be expanded, then the unit that calls the function must explicitly use the unit where the ancestor type is exposed.

Lets take a look at what exactly function inlining is. When you call an inline function what happens at the compiler level is that the actual code of function is expanded at the location of the call instead of a call being made to a function. A call translates into variables being pushed onto the stack, a jump being made, variables being popped off the stack, etc. So if there isn't a lot of code in a function then it makes sense to inline it.

AnsiSameText calls AnsiCompareText which is also Inline. If your are running under Windows then AnsiCompareText calls CompareString which is in Windows.pas. When these inline functions are expanded your call to AnsiSameText is actually becomes a call to CompareString from your unit.

Julian Bucknall has a rant about how the fact that Inline is only a hint to the compiler that your function is inlined. This is why inlining is only a hint. Your unit may not be able to have the expanded code in it because of a type or call that is declared in another unit that your unit does not use.

What does all this mean to you and your "No Hints or Warnings Policy"? Since Windows is used in the SysUtils unit you do not gain anything by excluding it from your uses clause. So put Windows back at the beginning of your uses clause and the warning will go away, and your program should not be any different. If you want to be cross platform compatible then do something like:

{$IFDEF MSWINDOWS}
Windows,
{$ENDIF}
{$IFDEF LINUX}
Types,
Libc,
{$ENDIF}

Excluding the Windows unit from your uses clause is important if you are going for cross platform compatibility, but if you are trying to reduce code bloat then you aren't accomplishing anything since SysUtils calls it directly, in fact that uses clause is directly from its uses clause.

Tuesday, November 30, 2004

Getting Rid of Delphi Warnings

Someone asked how to get rid of the Delphi warning:

"Unsafe typecast of 'Pointer' to 'TObject'"

The purpose of the "Unsafe" warnings is to let you know your code will not be easily compatible with .NET (or other safe platforms). If your target platform is only going to be Win32 then you can use the compiler directives:

{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
Also worth noting are the platform warnings. These were originally to let you know if your code was going to be compatible with Linux. So if you are only targeting Win32 (or any specific platform) you can disable these warnings with:
{$WARN SYMBOL_PLATFORM OFF}

These are also accessible via the Project / Options / Compiler Messages screen. Generally you should only disable a warning if you know it does not apply to your specific program. I should hope no-one ever disables all hits and warnings.

If you want to know the compiler directive version of the warning then just look in the project .cfg file for the -w lines added when you enable or disable a warning. Then just append {$WARN in front of it and OFF|ON} after it for most of the warnings.

Monday, November 29, 2004

Delphi Popularity

There has been a lot of fuss about the latest TIOBE Programming Community Index for November 2004. The first I noticed was David I's post, then Steve pointed out a post on Slashdot titled "Delphi Renaissance". Both commenting that Delphi has four green arrows (indicating a lot of growth). In fact the TIOBE site has a blurb about it as well. They actually asked Dr. Bob what his take on the growth was. One point everyone is missing is that these stats have shown that Delphi has been growing for a few months now, and all this growth is from before the Delphi 2005 release!

Here are the November numbers:

PositionDelta 1 YearProgramming LanguageRatingsDelta 1 YearStatus
1C17.992%+0.99%A
2Java14.804%-8.28%A
3C++13.865%-2.45%A
4(Visual) Basic10.529%+3.12%A
5Perl9.726%+2.04%A
6PHP7.586%+4.02%A
7Delphi/Kylix5.310%+3.77%A
8Python5.200%+3.43%A
9SQL3.003%-0.69%A
10C#1.504%-0.40%A
11JavaScript1.195%-0.72%A
(The top 11 since I don't consider SQL a programming language)

Delphi 2005 was released just at the beginning of November, so this data that was collected based on data before November will not show any activity from the release. So we should see Delphi really take off next month when these numbers include activity after the Delphi 2005 release.

If I were to attribute anything to these high Delphi growth numbers I would attribute BorCon 2004 and all the blogging. There were blogs created just for covering BorCon. So I guess since Delphi 2005 ( aka Diamondback ) was the central theme of BorCon I guess it could be the source of this growth.

It is worth noting that the author of this report removed Pascal from the Delphi / Kylix data for the first time this month. This means that the numbers are actually reduced from what they would have been had Pascal not been seperated out.

I did a write up on these numbers, in combination with some performance data, back in August. Then I pointed out that Delphi and Python were both growing like gangbusters, while C# was declining in popularity. I think Delphi only had a two or three green arrows then, while Python had four.

Wednesday, November 24, 2004

Some Answers to TDD

Test Driven Development (or TDD) is a programming methodology where you write a test for a feature, then write code that passes that test. Julian Bucknall shares some of his answers on TDD in his Blog.

TDD is something I am really interested in and am advocating. I think methodology is a lot more important then language, framework or platform when it comes to programming. I am reading Pragmatic Unit Testing in C# with NUnit By Andy Hunt, Dave Thomas. It provides a lot of good information on the subject. I'll have a book review here soon. I am also looking at picking up the new Unit Test Frameworks by Paul Hamill next.

David I on Software as a "Living Entity"...

David I. has another interesting post on Software as a "Living Entity".... It reminded me of the book The Little Black Book of Computer Viruses by Mark Ludwig. It talked about viruses as artificial life. You can really have fun with viruses since you need to consider this life cycle and self replication or it will really bite you!

Please note I don't advocate the use of viruses for distractive activities.

I guess that book was replaced with the The Giant Black Book of Computer Viruses which is also by Mark Ludwig. He has other works on viruses if you are really interested.

More Coding Peeves. . .

David I has a post about Coding Peeves. I agree with most of the ones he posted. Here are a few of mine he missed. If you see yourself here don't take it personally. I know I am opinionated. It is part of what makes me interesting! I imagine that some of my coding habits may annoy others, but they will learn to appreciate them.

1) try except blocks with nothing in the exception handler (or just a comment saying "ignore all exceptions"). For really small blocks (like one or two lines) this is can be tolerated, but is really undesirable. Too many times I see a whole screen full of code and an empty exception block. If they want to ignore a specific class of exceptions then they should only trap and ignore that class, but they should be as specific as possible. It is arrogant of the developer to assume they know of every possible exception that could be raised, and that none of them are important. I don't know how often I am tasked with tracking down some odd behavior only to discover the original programmer ignored the exception because they didn't expect this particular one. That is the thing about exceptions, they aren't always expected!

2) Failure to use classes, functions and procedures. Some programmers believe "code reuse" means copy, paste, modify. Maybe the still think their performance is measured on lines of code.

3) Ignoring compiler hints and warnings. Sure, it still compiles, but they are there for a reason. It is really bad when it has gotten out of hand on a really large project, then even if you want to eliminate the ones in the code you are working on you will have a hard time finding them. I personally have a no hints or warnings policy. If there is one I don't know how to clear then I comment it as such, although I have always discovered how to clear them later.

4) Overly strict adoption of Hungarian or reverse Polish notations. When you have complex objects you are working with these notations just turn your variables into alphabet soup! A name variable is a comment about what it contains. Using a notation that denotes the type is like a comment of "set I to 1" - it is redundant. The compiler knows the type and the IDE will tell you.

For example:

Lets say you have a OracleDataReader that is reading sales data. Now what makes more sense: oraDtaRdrSls or SalesData, let alone which is easier to type or refer to in conversation! Although I will allow that some people do like alphabet soup. Maybe that is what we should call the notation.

Another things to consider is if you later change the types of your variables then you need to rename all your variables. Good thing Delphi 2005 has built in refactoring! Time to give those variables in that code you inherited a meaningful name!

5)The use of single line comment characters over multiple lines. I think this is a favorite of the alphabet soup types who like typing extra meaningless characters. Plus if I need to go edit or add to the comment later then I have to worry about where the line breaks and adding new comment marks on each line.

For example:

// We take the integer variable I
// and set it to the value of 1
// oh, and Hi Mom!

vs.

(* We take the integer variable I and set it to the value of 1 oh, and Hi Mom! *)

That should do it for now. Hopefully no one gets me started again.

Tuesday, November 23, 2004

Delphi 2005 Launch Tour in Boise

Anders Ohlsson is coming to Boise as part of the Delphi 2005 US Launch Tour.

He will be here December 7th at 7 PM. This is in addition to our normal December meeting on December 2nd. This visit is jointly sponsored between BSDG and NetDUG.

Anders will be giving away a copy of Delphi 2005 to one lucky attendee, and there will be a discount and T-Shirts available for everyone else. We are getting our Christmas a couple weeks early this year! I expect this to be an incredible demo of a great product. Anders is a great presenter and always a lot of fun.

The meeting location is at our normal Washington Group International location, but we will be meeting in the large training room. It holds 120 people, so bring your friends! If you know any other devlopers get the word out and invite them too!

Delphi 2005 does Delphi for .NET, Delphi for Win32 and C# development. One of the really cool features it includes is Enterprise Core Objects II (ECO II). ECO allows you to build your .NET programs using a model driven approach. It both forward and backwards engineers existing databases and applications. You may recall that Rational said the next version of their product will support OCL (Object Constraint Language). Well, the last version, and this version of ECO both support OCL. This is the future of software development, and you can see it here on December 7th.

There will be updated directions with photos but I wanted you to mark your calendar now.

Factorials, Combinations and Permutations

A while back on the TDAG list Bob Murdoch was trying to figure out Combinations in Delphi. I wrote this code for him and anyone else who is interested. Combination needs Factorial, and I decided to through Permutation (which also needs Factorial) in for good measure. I added an optimization in on Combination that requires an additional parameter (AStop) on Factorial. (Thanks to Brian Mayland for pointing out a bug in my optimization.) If you are calling factorial directly then just leave AStop as 0 [Zero]. If you wanted to you could have an overloaded version of Factorial instead of using a default parameter.

The code is available under MPL or LGPL.

[.html] [.pas] [.zip]

Friday, November 12, 2004

Free Programming and Computer Science Books

Free Programming and Computer Science Books has quite a collection of books to choose from. Everything from the 1971 "How it works: The Computer" to "The .NET Developer's Guide to Windows Security" (All electronic books unless you print them out yourself.)

It is worth checking out!

UPDATE: There seems to some dispute on the copyright of the "How it works: The Computer" book, so it may be taken off-line. I guess it was printed in England and their copyrights work differently. Maybe the 1979 edition will be taken off line and we will just have the 1971 edition. So be warned that these links may die.