2

Is there a way in Delphi of defining a class's methods across multiple files ? I have a form that's horrendously big (close to 100k lines) and I'd like to split it up.

Edit : Class helpers are not a good tool in this case because you won't be able to set methods from the helper class as event handlers, which means you'll have to make "forwarding" event handlers, adding a lot of complexity.

Ken White
  • 123,280
  • 14
  • 225
  • 444
turn
  • 41
  • 6
  • No. The best you can get is having another file with single class helper where you can move some of the methods. – Dalija Prasnikar Dec 14 '22 at 09:18
  • 1
    Another solution would be using frames to split up the form functionality into separate files. But, it is hard to say what is the appropriate solution for you as you haven't given any details about your code. – Dalija Prasnikar Dec 14 '22 at 09:19
  • @DalijaPrasnikar This is what I plan on doing in the future, but the code is for now way too spaghetti to do that. I was hoping I could organize a bit by splitting it into files by UI element, then refactor file by file to untangle the thing. Having a 100k lines file makes it a pain to do anything, even the coloring of if/else breaks down. – turn Dec 14 '22 at 13:21
  • Also, who decides whether a question is a duplicate ? Because I don't agree with this assessment. – turn Dec 14 '22 at 13:22
  • It is a duplicate because that is the only thing that resembles to what you are looking for, But if you want your question to be reopened, you would have to add more detail about your exact problem. Right now it is pretty vague. Ultimately, the answer would most likely be no, there is nothing in the language that would help you. – Dalija Prasnikar Dec 14 '22 at 14:10
  • For the code block colouring I suggest using ``CnPack`` plugin. For the long code, try to separate code into another unit, that is not tightly coupled to the form or refactor it to use some parameters to pass over components, if necessary. – Delphi Coder Dec 14 '22 at 14:25
  • @DelphiCoder I am using CnPack. It seems to break down above 75k lines. And I would like to refactor, but things are so tightly coupled that it's almost impossible to do it without sinking weeks of work (It's literally using the tag and color of labels to store data...) – turn Dec 15 '22 at 07:35
  • Good luck! Also have a look at MMX Code Explorer. – Delphi Coder Dec 15 '22 at 07:46
  • You could use include files to split up your code. Or just split the class into parent/child. Or split by making elements into classes. – Rohit Gupta Dec 16 '22 at 13:34
  • @RohitGupta Would the included file be able to access everything from the main file (class definitions, etc) as if it was in the file ? Because if not it would just flood everything with errors and while compiling would work, it would be nigh impossible to make changes to the code. As for refactoring, as I mentioned in comments above it would take massive amounts of time, which is why this question was opened ; to look for an easier alternative. – turn Dec 19 '22 at 07:11

2 Answers2

1

There is no way to directly achieve what you are asking for, other than breaking the form code up into a number of smaller include files (as suggested by Rohit's answer).

However, composing a form (or any other source file) in Delphi from a collection of include files will solve one problem whilst introducing many more, possibly far worse than the original problem.

All may not be lost, though it is difficult to suggest alternatives without knowing more about the form in question. But here are a couple of ideas...

Page/Tab Control "Re-Parenting"

If it is a form with a page/tab control with many tabs each of which with a large number of controls and code, then one alternative might be to break the individual tabs out into individual forms with the content dynamically re-parented into the main form as required (either on demand or as part of form initialisation).

This could be as simple as providing a Panel control in each "child" form and setting the Panel.Parent to the corresponding tab control sheet (the controls parented onto the panel will "go with it". Use alClient alignment on the panel and corresponding alignment or anchor settings on the controls to preserve "responsive" layout when the control parent panel is moved from the "design-time" form to the "run-time" tab control.

The event handling and other code related to those controls would continue to reside in the decomposed "child" forms.

Caveat: You don't mention if this is a VCL or FMX project. I have used the above approach successfully with very large VCL projects in the past, but I have no idea if FMX supports the approach.

Business Objects

If there is no obvious UI decomposition that is possible, but the form contains a large amount of business logic, then it may be possible to simply refactor the business logic out into a business object (or objects).

Limit the form code to dealing with user interaction and UI updates and move all of the non-UI code out into separate files.

Deltics
  • 22,162
  • 2
  • 42
  • 70
  • Thank you for the answer ; it is a VCL project with a PageControl. Unfortunately I am asking this question precisely because refactoring is out of the question at the moment. Splitting it by tab is of course the way to go, but the tabs are too interlinked to be easily separated. – turn Dec 21 '22 at 11:56
  • I worked on a project some years ago with a legacy form split across several include files; I forget the reason why (I have a hazy memory that as a single file it was just "too big" for either the IDE or the compiler). It was a nightmare to work with; everyone who encountered it tried (and failed) to re-unify it. More Delphi modern versions might cope better though if so, as a highly unusual practice, this will likely have been by accident rather than design. I honestly think you would be better off properly refactoring, even if it takes a lot longer. Future you will thank you. – Deltics Dec 22 '22 at 06:56
0

What I have done in the past is to split my files as definition and implementations.

ClassA.PAS

unit ClassA;

type
//Class Definition

implementation

{$ ClassA.IMP}

It does not matter how many include files you have. As far as the compiler is concerned, it's just one long length of code. You can put each method in a different file if you wish. You can use any extension at all. I preferred to use IMP (not PAS) for the includes to deter junior programs from poking sticky fingers in.

When they look at the PAS file, they see the class definition, which is all they need for their task.

You can even nest include files, that is, call another include file from an include file. But that would get messy. I have used nested include files to structure compiler defines, company wide, application wide, etc. Where the application defines file would include the company defines.

Rohit Gupta
  • 4,022
  • 20
  • 31
  • 41