dmitrybv 3 Posted June 8 Hello If a project has many classes that are defined in different files, and the classes refer to each other, then at a certain stage a compilation error begins to occur: [dcc32 Fatal Error] EhLib.FMX…….pas(19): F2047 Circular unit reference to 'EhLib.FMX……..' To fix this error, you have to shove all the classes into one file and as a result, the project ends up with one huge file that is not convenient to work with. Who is coping with this problem and how? Share this post Link to post
Brian Evans 105 Posted June 8 I move my own units from the uses clause in the interface section to the implemenation section. An example would be two forms that access some of each other's properties and objects. They have each other listed in the implementation's uses clause. Share this post Link to post
dmitrybv 3 Posted June 8 If in unit1 I move a reference to unit2 to the implementation section, then I cannot use classes from unit2 in the interface section of unit1. Share this post Link to post
David Heffernan 2345 Posted June 8 Hard to answer without seeing how the classes and types are defined 3 Share this post Link to post
Remy Lebeau 1396 Posted June 8 4 hours ago, dmitrybv said: Who is coping with this problem and how? You need to de-couple the classes so they don't refer to each other directly anymore. Use interfaces or events/callbacks instead. 3 Share this post Link to post
David Heffernan 2345 Posted June 9 8 hours ago, Remy Lebeau said: You need to de-couple the classes so they don't refer to each other directly anymore. Use interfaces or events/callbacks instead. Interfaces and callbacks might be the solution, but I'm always very sceptical of people who will tell you the solution to a problem that hasn't been clearly stated. Share this post Link to post
Rollo62 536 Posted June 9 (edited) Beside other tools, I like Uwe Raabes Mmx CodeExplorer and here is another nice tool from Alexander Sviridenkov coping with that. Generally, like said before, you could consider to move critical references from the "interface uses" to the "implementation uses", wherever necessary, and to split up classes into interfaces and implementations in separate units. Edited June 9 by Rollo62 Share this post Link to post
Pat Foley 51 Posted June 9 (edited) Alternate way. Consider program schema to 'Broker' serving UI by listening to events In FMX you can use TControl where in VCL TWinControl usually needed. Meaning only deal with the components. The broker or server of Application sits in a Datamodule. This broker listens for User generated events and updates the Control UI in response. Also the broker updates the UI on timer events. Using java style to find controls ClassName 'TStringGrid' vs ClassType(TStringGrid) to find controls to assign the update. The FMX allows forms considered as TControls where in VCL screen.formname is used to find form needed. Stream in the forms dfm Controls change fixup~to bind the updates Need less timers Uwe's shows one cycle three deep on a project with 30 forms Alex's graph works well too. Edited June 9 by Pat Foley StringGrid was StringList Share this post Link to post
darnocian 84 Posted June 9 It would be awesome feature request if this problem were solved by the compiler. But I suspect we need to be able to allow forward declarations on all types first (e.g. records), before we can go cross unit. As mentioned before, if the stuff causing the circular reference is only needed in the implementation, moving the respective unit(s) referencing the respective the dependencies to the implementation may solve the problem. Otherwise, you need to have another unit that either implements the an interface/base class/abstract class dependencies that can then be used by the respective units where the circular issues exist. In this case, as general abstract strategies, the above techniques have been used to solve this type of problem, without getting into the specifics. 20 hours ago, dmitrybv said: To fix this error, you have to shove all the classes into one file and as a result, the project ends up with one huge file that is not convenient to work with. I am not so convinced by by this approach, as dmitry identified, it would not be very convenient long term. Some analysis/refactoring is definitely required. Share this post Link to post
Brandon Staggs 278 Posted June 10 22 hours ago, darnocian said: It would be awesome feature request if this problem were solved by the compiler. I don't think circular references need to be solved by the compiler. In my experience, this has always been a signal that two things which shouldn't be are coupled too tightly and some refactoring is in order. 1 Share this post Link to post
dmitrybv 3 Posted June 10 If we compare this feature with other programming languages, then, for example, in C# you can separate the implementation of classes in several files and you can declare references to any public classes and any internal classes in the assembly, regardless of in which files the class is declared. Perhaps in Delphi we need to introduce such a concept as an assembly or library, within which classes can refer to each other in the interface part. In general, when developing classes, you want to operate only with such concepts as a library and a class, but you don’t want to think about which file it should be described in so that it can be used in other classes of the library. Share this post Link to post
Uwe Raabe 2057 Posted June 10 The plethora of working Delphi programs are proof that there already exist concepts to eliminate dependencies between units. They may differ from those available in other programming languages, though. IMHO, circular dependencies should be eliminated even if they appear in implementation sections and thus making the code compile. I wouldn't support any request to extend that in any way leading to more circular dependencies. 6 Share this post Link to post
Brandon Staggs 278 Posted June 10 1 hour ago, dmitrybv said: If we compare this feature with other programming languages, then, for example, in C# you can separate the implementation of classes in several files and you can declare references to any public classes and any internal classes in the assembly, regardless of in which files the class is declared. Perhaps in Delphi we need to introduce such a concept as an assembly or library, within which classes can refer to each other in the interface part. In general, when developing classes, you want to operate only with such concepts as a library and a class, but you don’t want to think about which file it should be described in so that it can be used in other classes of the library. Nah, it is fine the way it is. Delphi Pascal already provides everything you need to decouple code and even throw partial implementations into myriad units if you really want to. The compiler is already lenient enough for those who are in a rush or don't care to decouple their code, allowing units to require each other to build as long as you keep the interface/implementation dependencies straight. Share this post Link to post