Jednakże lepiej by było, abyś przeczytał ze zrozumieniem co napisałem.
A nie pisałem o form designer tylko o LiveBindings i jego edycji.
To mi się zmieszało. Nie używałem LiveBindings nigdy, więc nie wiem jak to działało. Kiedyś byłem na konferencji dotyczącej zdaje się XE3 i tam się tym szczycili, więc pewnie działało.
Naprawdę? Ile Ty masz lat, że wierzysz we wszystko co na konferencjach mówi producent? A co ma powiedzieć, że nie działa?
Dam przykład (kto był w tym roku w Rawie Mazowieckiej, ten może pamięta); Moskwa opowiadał o FMX, w pewnym momencie wspominał o klasie TLocation (tak to się chyba nazywa, chodzi o obsługę GPSa w urządzeniach) i mówi, że to generalnie nie zawsze działa. Na dodatek potrafi zawiesić urządzenie. Mina przedstawicieli producenta - bezcenna, zwłaszcza jak głosy na sali potwierdzają - "tak ja też spotkałem się z tym problemem"....
Poza tym, szczycili... Taki binding powinien być w Delphi co najmniej od ponad 10 lat!
Już nie chce mi się pisać, że w pierwszej wersji działało to i owszem - na prezentacji. Sama wydajność była poniżej krytyki, tak słaba, że dyskwalifikowała to rozwiązanie przy obsłudze list (czyli binding z listy obiektów do np. ListView; zresztą na SO można znaleźć takie tematy). Żeby oddać sprawiedliwość, to problem nasilał się w przypadku FMX. Dla VCL działało to znośnie.
A teraz to Delphi oni czołówkę, a nie na odwrót...
Ale to nie jest tak, że tylko wyklikać albo w ogóle. W kodzie też to można ogarnąć przecież. To są dwie różne drogi to osiągnięcia tego samego celu.
Czy ja pisałem, że się nie da tego z kodu zrobić?
Nie, ja pisałem, że nie ma do tego dokumentacji - porządnej i wyczerpującej.
Nie wierzysz, to proszę tutorial:
http://docwiki.embarcadero.com/RADStudio/Berlin/en/Programatically_Binding_Created_Objects
I pierwsze zdanie:
"Caution: The programmatic method described here is NOT the standard way to implement binding expressions."
Nosz urwa spadłem z krzesła...
Pewnie, można powiedzieć - przecież to nic i czepiam się. Można. Tylko dla mnie programowanie to nie zabawa, tylko podstawa egzystencji.
A więc jak mi producent pisze, że to da się ale de-facto jest to hack, to ja się zaczynam poważnie zastanawiać, od której wersji się nie da.
Bo tak, przecież ostrzegali...
Generalnie to, jak coś działa pod spodem, nie powinno Cię, jako programisty wykorzystującego bibliotekę, interesować. Chyba, że masz naprawdę specyficzne wymagania i oczekiwania. Dlatego możesz zajrzeć do kodu.
Raczysz żartować?
Programista ma się nie interesować jak to działa, tylko bezkrytycznie używać?
Nie mówię, że bezkrytycznie używać. Nie wiem, czy się nie rozumiemy źle. Naturalnie należy znać zależności między obiektami itp. Ale jeśli mam obiekt, który ma metodę:
to tak naprawdę ważne jest dla mnie, co ta metoda robi, a nie w jaki sposób. Tak jest ZAZWYCZAJ. Bo załóżmy metoda:
to już może mieć znaczenie, czy kwadrat jest rysowany bezpośrednio przez GPU, czy też przez jakieś obiekty systemowe. Ale w takich wypadkach wystarczy mi ta wiedza. Bo co mnie interesuje sposób w jaki ten kwadrat jest rysowany?
Delphi to takie narzędzie, które uczy bardzo, ale to bardzo złych nawyków. A najgorsze jest to, że sam producent to promuje.
Efekt tego jest taki, że gro użytkowników Delphi nie programuje obiektowo. Oni używają obiektów, a to nie jest to samo.
OK, z tym się zgodzę. Faktycznie w Delphi jest za dużo funkcji, za mało metod.
Z kolei z tym ja się nie zgodzę. Bo tak było, ale to się zmienia.
Popatrz sobie na moduł IOUtils na przykład - to samo jest dostępne jako kod proceduralny, ale tam mamy śliczne metody klasowe.
Tego jest coraz więcej - i bardzo dobrze.
Ale to są rzeczy ciągnięte, jak sam zauważyłeś, od wielu lat. I teraz byłoby lekkim strzałem w kolano np. usunięcie funkcji format. Chociaż mogliby utworzyć np. klasę String.
Mówiłeś, że w której wersji piszesz? Ostatnio na XE5, dobrze pamiętam?
Musze Cię zmartwić, nie znasz narzędzia którego używasz, ponieważ jest to od wersji XE3.
I nie, nie jest tak że String jest klasą (to by był dopiero hardcore - tworzyć i zwalniać każdego stringa :D), ale jest tak, że dla typów prostych można utworzyć class helper.
A tu masz opis TStringHelper:
http://docwiki.embarcadero.com/Libraries/Seattle/en/System.SysUtils.TStringHelper_Methods
Ale wtedy posypałyby się stare kody, bo wielkość liter w Delphi nie ma znaczenia. Więc naprawdę trzeba by ostro przeryć całe środowisko, co skończyłoby się brakiem kompatybilności wstecznej. Już były problemy z migracją, gdy string przestał być ansi, a zaczął być unicodowy.
Bez przesady, to nie jest aż tak wielki problem jaki miał właśnie miejsce z ANSI/Unicode oraz kompilatorem 32/64 bit. Chociaż przy poprawnie napisanym kodzie, to tez nie był duży kłopot.
BTW - wiedziałeś, że od wersji XE3 w Delphi jest zero-based-string? Domyślnie OFF :D
Poza tym porządny wsparcie dla porządnego namespace bardzo by pomógł, a nie takie nie wiadomo co to jest, co jest.
Prawda jest taka, że rozwój samego języka i RTLa napędza FMX, ponieważ kod wieloplatformowy to naprawdę poważny problem do rozwiązania.
No i pchają tego FMX na siłę... Zastanawiam się tylko kiedy to zdechnie na amen :D
Trzeba sobie zdać sprawę z tego, że Delphi faktycznie niektóre rzeczy robi nie w sposób obiektowy. Ale taka jest po prostu specyfika języka. Jednym to pasuje, innym nie. Ale chyba nie można powiedzieć, że przez to Delphi jest lepsze albo gorsze.
Chodzi Ci o funkcje podstawowe w RTL? Co się dziwić - Delphi to był zawsze Windows, a czyste WinAPI przeca jest proceduralne...
Mi to nie przeszkadza, ale zaczyna to być coraz ładniej opakowane.
I fajnie.
To pokaż mi jak to robisz, ciekawym.
Może faktycznie czegoś nie wiem i się dowiem.
Zadam kilka pytań pomocniczych:
- Gdzie są tworzone, utrzymywane obiekty DAL (wszystko co do bazy danych potrzebne; connection, query, itd.)?
Teoretycznie powinny być na DataModule. Natomiast ja robiłem to trochę inaczej. Miałem swoją własną klasę do obsługi zapytań, wszystkie obiekty bazodanowe (w sensie właśnie connection, query, itp) tworzyłem dynamicznie.
- Jak budujesz formatki?
Jak. Normalnie :) Kładę kontrolki na formę i tyle. Tutaj nie ma żadnej filozofii. Chyba, że masz coś konkretnego na myśli.
- Gdzie jest logika, np. walidacja danych przed zapisem? Albo jęsli wartość w polu X = Y, to przelicz dane w DataSet
OK, walidacja danych to jest kwestia po stronie formatki.
A co ma prezentacja danych do jej walidacji? ;-)
Wiesz, moje pytania były tendencyjne - praktycznie wszyscy programują w ten sposób.
Można to zrobić koszernie, ale trzeba się napocić...
Ale to nie jest logika jaką miałem na myśli.
Nie jest. Ale jest z nią ściśle powiązana i na pewno nie powinna być na formatce, a w modelu danych.
Tylko to Delphi nie ma modelu danych by-design...
Po prostu dostarczenie do obiektu poprawnych danych. Co do przeliczania w DataSet. Jeśli to jest mało skomplikowane (załóżmy dosłownie kilka warunków), to można to zrobić bezpośrednio w zdarzeniu. Natomiast, jeśli jest coś bardziej skomplikowanego, to nikt Ci nie broni napisać sobie odpowiednich klas do tego z całą hierarchią dziedziczenia i w ogóle. Wszystko może sprowadzić się do wywołania w zdarzeniu jednej metody, obiektu który to wszystko ogarnie.
I to jest właśnie Delphiowe podejście... raz tak, a raz siak. To jest drogi Kolego bardzo zły nawyk.
No chyba, że lubimy debugować czary, bo nie wiadomo co ta aplikacja robi - a potem się okazuje, że ktoś dopisał jakiś kod w zdarzeniu (bo tak, kliknął sobie na formatce w zdarzenie komponentu, wpisał dwie linie kodu i zadowolony) i wszystko idzie w rozsypkę.
Jasne, to nie jest problem Delphi tylko programowania w ogóle - jak coś robić, a jak nie i dlaczego nie.
- Jak zapisywane są dane dla skompilowanego, niech będzie, formularza? Sokmplikowanego, tj. takiego który posiada Master, Detail (kilka) , Subdetail (kilka)?
Nie rozumiem pytania.
- Ile jest wspólnego kodu? Np. zapis, usuwanie, walidacja danych?
Tyle, ile sobie napiszesz.
Ja sobie napisałem - jedną klasę, która zarządza tym wszystkim niezależnie od skomplikowania modelu danych.
Ale wiem, że to nieczęsta praktyka; częstsza jest taka.
Kopiuj
try
conn.BeginTransaction;
if dsMaster.State in dsEditStates then
dsMaster.Post;
if dsDetail.State in dsEditStates then
dsDetail.Post;
conn.Commit;
except
conn.Rollback;
raise;
end;
I powtarzamy taką wyliczankę na każdym okienku liczonym w setkach.
Wypas :)
Moje podstawowe bóle to były (a były, bo to czas przeszly):
- Edycja formatek
- Utrzymywanie formatek
- Dziedziczenie formatek
Hmm, z tym w Delphi nigdy nie miałem żadnych problemów. Wystarczyło odpowiednio poukładać kontrolki na panelach, porobić anchory itd. Natomiast bardzo mnie denerwuje dziedziczenie formatek w C#, które dość często nie działa tak jak powinno. Ale to inna kwestia.
Nie chodzi mi o to, że edytor formatek źle działa w Delphi. Działa OK.
Chodzi o to, że każdą z nich trzeba zrobić. Rozwijać i utrzymywać.
Wyobraź sobie, że masz główny obiekt w Twoim systemie i zaistniała potrzeba dodawania nowego atrybutu (niech będzie, że to pole w tabeli).
Banał prawda? Prawda.
A teraz ten obiekt jest wykorzystywany na 20 albo i 100 formatkach i na każdej z nich ma być dodane to nowe pole + dodatkowa logika zależna od wartości tego pola, która ingeruje w logikę na innych formatkach.
No to mamy bagno...
Zrobienie tego jest proste, ale cholernie żmudne i na pewno urodzą się nowe błędy.
A nie lepiej by było dodać ten atrybutu do modelu danych + dopisać te kilka linii kodu do logiki i koniec?
Reszta, włącznie z rozbudową wszystkich formatek, robi się sama.
- Wyklikane komponenty niewizualne, które część ustawień mają w kodzie a część w DFM.
Ustawienia w kodzie powinny być ustawieniami dynamicznymi. Jeśli już wyklikujesz sobie komponent niewizualny, to powinieneś jak najwięcej się da ustawić właśnie w ObjectInspectorze. Ale to chyba normalne, nie?
Raczej typowe. Natomiast ja jestem absolutnie przeciwny takiemu postępowaniu.
Wolę kod, ponieważ wszystko widzę w jednym miejscu. Zmieniam w jednym miejscu i działa.
Tak jest prościej i bezpieczniej.
Ale nie zawsze tak robiłem, kiedyś tez uważałem to za swego rodzaju fanaberię; do czasu...
Natomiast ja mam dość specyficzne potrzeby, a podstawowa z nich brzmi: jeden kod do wszystkiego. Aplikacja różni się istotnie od instalacji. Nie chcę robić ifologii do zmiany zachowania, widoku i logiki.
No i dobrze bo do tego robi się odpowiednie struktury klas :)
Naprawdę chciałbym je zobaczyć, jakiego miałbyś pomysła na rozwiązanie pewnych kwestii. To byłoby szalenie ciekawe :)