Jak zarzadzac Unitami....

0

Witam

ostatnio zaczalem pisac wieksze programy, z wykozystaniem wielu Unitow pisanych rownolegle
(przez jedna osobe). Po pewnym czasie zuwazylem ze dobrze by bylo gdybym mogl z UnituA wywolac funkcje z UnituB. To jest proste - trzeba bylo dodac go do sekcji uses . Problem (tak mi sie wydaje) pojawia sie gdy w UnicieB chce wykozystac funkcje z UnituA. Bo jak go dodam do sekcji uses to pojawia sie blad

[Fatal Error] UnitPracownicy.pas(7): F2047 Circular unit reference to 'UnitPracownicy'

mozna dodac ten UnitA w sekcji uses pod slowem implementation ale nie jestem przekonany czy jest to najlepsze rozwiazanie. Tworzy sie w ten sposob jakies dziwne petle odwolan. Na dluzsza mete prowadzi to do sytuacji w ktorej nie do konca wiem co podlaczam, majac juz 10 innych unitow wywolujacych sie nawzajem.

Czy jedyna metoda zapanowania nad szybko powstajacym Unitowym Chaosem jest przemyslane ich laczenie?
Moze sa jakies ogolne zasady kierujace powstawaniem struktory Unitow??

Doszedlem juz do tego ze mam Unit _z_czesto_uzywanymi_funkcjami ktory dolaczam do wiekszosci
pozniej tworzonych. Ale chetnie poznalbym doswiadczenia innych w tej dziedzinie... Nie chcialbym tez tracic czasu na cos co zostalo juz dawno wymyslone...

pozdrawiam i zapraszam do
opisywania swoich metod, spostrzezen i pomyslow.

PS
Jesli nie jasno sformuowalem zagadnienie,
napiszcie to postaram sie to naprawic

0

Wydaje mi się że uses pod implementation to nic złego. :) Samo Delphi umieszcza tam odwołania do unitów z projektu i nie powoduje to żadnych problemów.

0

Najlepiej jest robić strukturę nie zawierającą pętli. Jeśli coś ma być <ort>urzyte </ort>w innych Unitach, to wydziel te struktury do osobnego pliku. Im więcej pętli zrobisz, tym masz większe szanse na "gonienie własnego ogona", czyli naprawiając błąd w jednym module tworzysz go w drugim itd...

A to przykre może być ;)

0

To sa tzw. odwolania cykliczne wynikajace z blednego zaprojektowania aplikacji i podzialowi na moduly. Rozwiazaniem takiej sytuacji jest utworzenie modulu UnitC, w ktorym beda znajdowac sie funkcje czy klasy wykorzystywane przez modul UnitA oraz UnitB.

0

no dobra,
ale jak to rozwiazac jak mam powiedzmy trzy okienka, kazde w innym module.
I chcialbym miec mozliwosc z kazdego z nich wywolac pozostale dwa?

moglbym napisac Unit0 w ktorym bylyby procedury wywolujace poszczegolne okienka,
i dolaczyc go do wszystkich pozostalych, ALE
zeby wywolywac okienka trzeba dolaczyc odpowiednie Unity.
A jak nastepnie podlacze ten Unit0 dokazdego Unitu z okienkiem
(zeby miec dostep do procedur wywolujacych pozostale okienka)
to na nowo powstana te ODWOLANIA CYKLICZNE...

czy w takim przypadku musze ujmiescic te wszystkie okienka w jednym Unicie?
Do tej pory stosowalem domyslne rozwiazanie - czyli: 1 Formularz = 1 Unit...
ale moze to nie tedy droga...?

0

Też miałem kiedyś taki problem. Moje remedium to:

Zrób oddzielny Unit z klasą (lub zmiennymi/tablicą, zależy jak rozbudowana ma być ta współpraca) zawierającą szereg pól TForm. Z tegu Unitu <ort>kożystają </ort>wszystkie pozostałe okienka, przy czym przy ich tworzeniu wpisują swój wskaźnik w odpowiednim polu klasy. Poprzez tę klasę będziesz miał dostęp do każdego okienka bez tworzenia pętli.

0

nie wiem czy dobrze rozumiem, ale problemem jest odwoływanie się do dwóch form <ort>na wzajem</ort> (na krzyż)?
jeżeli dopiszemy moduł do sekcji uses pod implemetation i dyrektywą dołączającą formatkę to wszystko ładnie śmiga ;p z resztą sprawdziłem przed chwilą dla pewności ( http://pastebin.4programmers.net/231 ).

0
AklimX napisał(a)

...

ta to już napisał autor w pierwszym poście ... wydaje mi się że takie rozwiązanie w ostatecznośći nie jest niczym złym, po to to jest, jednak jeśli jest to aplikacja "modułowa" i doszło do czegoś takiego to jest to ewidentny błąd spowodowany nieprzemyśleniem projektu

0

Adamo: Jakoś nie zauważyłem. Jeśli są tam funkcje, które się wzajemnie ciągle wywołują, to faktycznie, lepiej wyrzucić je do osobnego modułu (czyt. unitu, jak kto woli). Jednak omijanie na siłę dowiązań cyklicznych przy najprostszych odwołaniach do innych form mija się z celem. Wtedy kod staje się jeszcze bardziej zagmatwany.

0
Adamo napisał(a)

... i doszło do czegoś takiego to jest to ewidentny błąd spowodowany nieprzemyśleniem projektu

No i wlasnie tu jest sedno mojego pytania!

Jak powinien wygladac "Przemyslany projekt"?
Czym sie kierowac tworzac go?

Szczegolnie jesli nie jest to jakis mega-projekt z gotowym
planem, tylko aplikacyjka, ktorej szczegolowe opcje i zadania
pojawiaja sie w trakcie tworzenia programu
(to sie chyba nazywa Iteracyjny Cykl Zycia Alikacji...)

0
Johny_Morfina napisał(a)

Jak powinien wygladac "Przemyslany projekt"?
Czym sie kierowac tworzac go?

Na początku był rysunek narysowany patykiem w popiele ogniska i od tego proponowałbym zacząć - narysować schemat całej aplikacji, jej zachowań itd. Lepiej poświęcić tydzień na opracowanie schematu niż potem miesiąc na przerabianie jej.

0
Adam.Pilorz napisał(a)

lepiej wyrzucić je do osobnego modułu (czyt. unitu, jak kto woli)

właśnie tu mówiąc o module nie mówię o unicie - bo zrobienie np dwóch nawzajem odwołujących się wzajemnie form w dwóch unitach nie jest niczym złym

0

Podstawowe fazy powstawania projektu to:

Planowanie -> Specyfikacja -> Kodowanie -> Testowanie -> Wdrozenie

Najwiecej czasu powinno sie poswiecac procesowi specyfikacji. Polega on na szczegolowym opisaniu modulow, funkcji, struktury bazy danych. Wymaga duzego skupienia i rozwazenia za i przeciw.

Tyle w teorii. Taki schemat moze i jest skuteczny przy duzych projektach, przy malych jednoosobowych czlowiek nie posiweca tyle czasu na tworzenie sepcyfikacji. Ja np. nie moge sie doczekac kodowania i czesto od razu zabieram sie za pisanie ;) Wczesniej opracowuje sobie mini specyfikacje, tj. strukture tabel bazy danych oraz podstawowe moduly. Duzo pomyslow wychodzi pozniej w praniu. Oczywiscie nie raz moja wada w postaci braku cierpliwosci wychodzila mi bokiem ;) Okazywalo sie ze wszystko nad czym pracowalem kilka godzin jest do wyrzucenia bo mozna to zrobic lepiej. Jak widac czasami warto poswiecic wiecej czasu na przemyslenie tego co sie chce robic.

Ja wyznaje zasade malych kroczkow: kodowanie -> testowanie -> kodowanie -> testowanie itd.

0
Adam Boduch napisał(a)

Ja wyznaje zasade malych kroczkow: kodowanie -> testowanie -> kodowanie -> testowanie itd.

to tak jak ja :D
Co do rzucania się w kod, to faktycznie można się nieźle naciąć. Ostatnio napisałem parser, który miał kolorować składnię w odpowiednich tagach ( para [code] [/code] ) - ponad 100 linii kodu (i to była tylko podstawa, bez koniecznej funkcjonalności), po czym stwierdziłem, że dodając puste tagi kodu na początku i końcu tekstu można go bardzo łatwo sparsować uzywając prostego regexpa i preg_replace_callback(). (Początkowa wersja też była na regexpach, ale strasznie mi się nie podobała, bo powstawało dużo śmieci).

Pozdrawiam i życzę owocnych/przemyślanych(chociaż w części) projektów :) Aklimx

0

Jak powinien wygladac "Przemyslany projekt"?
Czym sie kierowac tworzac go?

Szczegolnie jesli nie jest to jakis mega-projekt z gotowym
planem, tylko aplikacyjka, ktorej szczegolowe opcje i zadania
pojawiaja sie w trakcie tworzenia programu
(to sie chyba nazywa Iteracyjny Cykl Zycia Alikacji...)

Refactoring !

Regularne sprzątanie powinno rozwiązać problem. Co pewien czas (naturalnym momentem jest ukończenie modułu) przeglądasz kod i wyłapujesz elementy które są:

  • zbyt nieczytelne
  • kilka razy powtórzone

Następnie poprawiasz je (to już zależy od sytuacji)

0

Można by także użyć interfejsów :)

Pierwszy: IWindow - odpowiadałby za konkretne okno (np. Show, Hide)
Drugi: IWindowEnumerator - zawierałby listę interfejsów IWindow oraz mógłby zawierać funkcje odnoszące się do wszystkich okien albo ich grup. Później program mógłby być łatwo rozszerzony.

W sekcji initialize każdego modułu z oknem zawarty byłby kod dodający interfejs tego okna do IWindowEnumerator, a w finalize - usuwający go z listy.

To była taka mała podpowiedź :-)

0

Ja zawszę mam w projekcie moduły
GlobalVar
GlobalConst
GlobalTypes
GlobalFunctions

itd, w zależności od projektu. Odwołań cyklicznych nie stosuję nigdy, tylko zawsze używam trzeciego modułu jako "bufora"

0
Oleksy_Adam napisał(a)

Ja zawszę mam w projekcie moduły
GlobalVar
GlobalConst
GlobalTypes
GlobalFunctions

nie jestem pewien o czym mówisz ale czy chodzi ci o to że wszystkie np funkcje masz w unicie GlobalFunctions ? to przecież bez sensu - powstają kilumetrowe unity i równie dobrze możnaby to wszystko wsadzić w jeden

1 użytkowników online, w tym zalogowanych: 0, gości: 1