Suppose I have two records: Person and Animal. Each record is in a separate package.
Package persons:
with animals;
use animals;
package persons is
type person is record
...
animalref: animalPOINTER;
...
end record;
type personPOINTER is access person;
end persons;
Package animals:
with persons;
use persons;
package animals is
type animal is record
...
ownerref: personPOINTER;
...
end record;
type animalPOINTER is access animal;
end animals;
I have Circular Unit Dependency here, and compiler produces fatal error.
Does anyone have a pattern to address such issue ?
Thanks!
To resolve circular dependencies: Then there are three strategies you can use: Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.
A cyclic dependency is an indication of a design or modeling problem in your software. Although you can construct your object graph by using property injection, you will ignore the root cause and add another problem: property injection causes Temporal Coupling. Instead, the solution is to look at the design closely.
Therefore, you experience circular dependency only once you have created the second column. The correct solution to avoid this is to restrict the list of columns that the calculated column depends on, by using ALLEXCEPT or REMOVEFILTERS and keeping only the table's primary key.
By running a cli command npx madge --circular --extensions ts ./ we can quickly get a list of circular dependencies of all . ts files in current directory and its subdirectories. That's it! Now you see where you have circular dependencies and can go and fix it.
You need limited with
, which was introduced to address exactly this problem. See the Rationale for Ada 2005, section 4.2.
Animals
and Persons
are symmetric (my editor has adjusted the layout and casing; I’ve added one record component to each so the demo program, below, can print something):
limited with Animals;
package Persons is
-- One of the few things you can do with an incomplete type, which
-- is what Animals.Animal is in the limited view of Animals, is to
-- declare an access to it.
type AnimalPOINTER is access Animals.Animal;
type Person is record
Name : Character;
Animalref : AnimalPOINTER;
end record;
end Persons;
limited with Persons;
package Animals is
type PersonPOINTER is access Persons.Person;
type Animal is record
Name : Character;
Ownerref : PersonPOINTER;
end record;
end Animals;
The demo program has the full view of Animals
and Persons
. This example is pretty clumsy; you may be able to organise things better by adding subprograms to Animals
and Persons
. Note that the body of Animals
can (and must) with Persons;
if it needs to use anything in Persons
.
with Ada.Text_IO; use Ada.Text_IO;
with Animals;
with Persons;
procedure Animals_And_Persons is
A : Persons.animalPOINTER := new Animals.Animal;
P : Animals.PersonPOINTER := new Persons.Person;
begin
A.all := (Name => 'a', Ownerref => P);
P.all := (Name => 'p', Animalref => A);
Put_Line (P.Name & " owns " & P.Animalref.Name);
Put_Line (A.Name & " is owned by " & A.Ownerref.Name);
end Animals_And_Persons;
which when compiled and run gives
$ ./animals_and_persons
p owns a
a is owned by p
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With