Jump to content
Sign in to follow this  
Uwe Raabe

On The Design Of Uses Clauses

Recommended Posts

While working on a tool for cleaning up uses clauses I stumbled upon this beast (slightly changed to protect the innocent):

{$if defined(DEBUG) or defined(DEBUG_SPECIAL)}
uses
{$ifend}
{$IFDEF DEBUG}
  dialogs
{$ENDIF}
//<some comment about the following ifdef>
{$IFDEF DEBUG_SPECIAL}
  mmsystem, // timeGetTime()
  messages
{$ENDIF}
{$if defined(DEBUG) or defined(DEBUG_SPECIAL)}
  ;
{$ifend} 

If you are only looking for uses clauses inside some Delphi sources and try to avoid a full featured parser, you will have a pretty hard job to detect, parse and interpret that one correctly.

 

So, if you are interested to make any use of such a tool, please do me a favor: Don't write your code that way! It is hard to read for humans anyway.

  • Like 1

Share this post


Link to post

A good tool must handle comments and conditionals correctly IMHO.

But it'll not be easy.:classic_biggrin:

Share this post


Link to post

Well, the actual problem here are the conditionals around the uses keyword and the closing semicolon. The rest inside is fine.

 

This version is handled without problems:

{$if defined(DEBUG) or defined(DEBUG_SPECIAL)}
uses
{$IFDEF DEBUG}
  dialogs
{$ENDIF}
//<some comment about the following ifdef>
{$IFDEF DEBUG_SPECIAL}
  mmsystem, // timeGetTime()
  messages
{$ENDIF}
  ;
{$ifend} 

 

Share this post


Link to post

Yes this look like a nightmare, if you want to parse the source and not only create a AST

Share this post


Link to post
3 hours ago, Uwe Raabe said:

Well, the actual problem here are the conditionals around the uses keyword and the closing semicolon. The rest inside is fine.

 

This version is handled without problems:


{$if defined(DEBUG) or defined(DEBUG_SPECIAL)}
uses
{$IFDEF DEBUG}
  dialogs
{$ENDIF}
//<some comment about the following ifdef>
{$IFDEF DEBUG_SPECIAL}
  mmsystem, // timeGetTime()
  messages
{$ENDIF}
  ;
{$ifend} 

 

I have been pondering the problem myself, as I want to reorder the uses clauses in a large number of units. The variations imposed over the years by thoughtless developers make the task a good deal more challenging than it ought to be:

uses

  OneUnit, Another, MyThird

, Fourth, {NoLongerUsed,} 

StillMore {Why here?}, 

Last

;

 

Conditionals obviously add to the fun. Moreover, I want to organize so that Delphi library modules are in the first grouping, then third-party, and last, units of the application. And then, of course, to provide for walking the file tree and applying changes to each application module found in the map file. 

Share this post


Link to post
1 hour ago, Bill Meyer said:

Moreover, I want to organize so that Delphi library modules are in the first grouping, then third-party, and last, units of the application. And then, of course, to provide for walking the file tree and applying changes to each application module found in the map file. 

Are you interested to do some testing?

Share this post


Link to post
10 minutes ago, Uwe Raabe said:

Are you interested to do some testing?

Yes, I could do that. I assume, however, that you are implementing for v14, not for earlier versions? Most of my work is in D2007, where I have literally thousands of such uses clauses to work with. 

Share this post


Link to post
1 hour ago, Bill Meyer said:

I assume, however, that you are implementing for v14, not for earlier versions? Most of my work is in D2007

I am referring to a command line tool.

Share this post


Link to post
3 minutes ago, Uwe Raabe said:

I am referring to a command line tool.

Well, that would be very interesting. I would be happy to do some testing.

Share this post


Link to post
On 7/18/2019 at 9:44 PM, Bill Meyer said:

Moreover, I want to organize so that Delphi library modules are in the first grouping, then third-party, and last, units of the application. And then, of course, to provide for walking the file tree and applying changes to each application module found in the map file. 

That's exactly the scheme I came to. I also avoid using units in impl. section except for app's forms.

Share this post


Link to post
4 hours ago, Fr0sT.Brutal said:

That's exactly the scheme I came to. I also avoid using units in impl. section except for app's forms.

Actually, I find it is better to add references in the implementation section, if they are not needed in the interface. Unit dependency cycles should always be avoided, but there are tools which can help you with that (MMX, Delphi Unit Dependency Scanner), and the need for such cycles is always indicative of design problems. 

In general, keep scope everywhere as narrow as possible.

Share this post


Link to post
16 minutes ago, Bill Meyer said:

In general, keep scope everywhere as narrow as possible.

Amen!

Share this post


Link to post
On 7/18/2019 at 2:44 PM, Bill Meyer said:

I have been pondering the problem myself, as I want to reorder the uses clauses in a large number of units. The variations imposed over the years by thoughtless developers make the task a good deal more challenging than it ought to be:

uses

  OneUnit, Another, MyThird

, Fourth, {NoLongerUsed,} 

StillMore {Why here?}, 

Last

;

 

What is the purpose of keeping {NoLongerUsed,} in the uses clause? If it compiles, it can be removed, right?

 

Also on StillMore {Why here?}, ... why would there be such indication? If it doesn't compile without StillMore then it should be there, no?

 

I don't understand these concepts, I only set those units in uses clause that need to be there. I follow compiler and hints what needs to be there. If it compiles without units, I don't put them there.

Share this post


Link to post
9 minutes ago, Mike Torrettinni said:

What is the purpose of keeping {NoLongerUsed,} in the uses clause? If it compiles, it can be removed, right?

 

Also on StillMore {Why here?}, ... why would there be such indication? If it doesn't compile without StillMore then it should be there, no?

 

I don't understand these concepts, I only set those units in uses clause that need to be there. I follow compiler and hints what needs to be there. If it compiles without units, I don't put them there.

Legacy code is its own excuse. Whatever the reasons may have been, these are examples which exist now, and which I need to parse out without damage to the rest. With over 2,000 units to process, and most containing uses clauses in both interface and implementation, the why of what is there is not my concern. Cleaning is my focus. And NOT by hand.

Share this post


Link to post
7 minutes ago, Bill Meyer said:

Legacy code is its own excuse. Whatever the reasons may have been, these are examples which exist now, and which I need to parse out without damage to the rest. With over 2,000 units to process, and most containing uses clauses in both interface and implementation, the why of what is there is not my concern. Cleaning is my focus. And NOT by hand.

I don't envy you, at all. I'm cleaning up my own code and it takes a lot for each unit, form, especially if redesign is needed. The easiest is decoupling forms, but some redesigns take time, too much time.

Share this post


Link to post
50 minutes ago, Mike Torrettinni said:

I don't envy you, at all. I'm cleaning up my own code and it takes a lot for each unit, form, especially if redesign is needed. The easiest is decoupling forms, but some redesigns take time, too much time.

It's not always fun. 😉 But it is a continuing challenge.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×