Darmowa i prosta biblioteka do SQLite

0
furious programming napisał(a):
Mr.YaHooo napisał(a):

Nie mniej jednak wielu początkujących programistów Delphi/C++ Builder'a stosuje upychanie całości na formatkach.

Nigdy nie oceniaj jakości technologii na podstawie losowego, gównianego kodu, napisanego przez kogoś, kto nie potrafi pisać dobrego kodu. Nigdy i żadnej technologii, bo to nie technologia winna, że jej użytkownik jest dzbanem. ;)

A jeśli porządny, posiadający architekturę kod jest przypadkiem, a spagetti na GUI statystyczną normą ?
Jak ktos ma myślenie nie ustawione pod tezę, to mu to do myślenia daje.

Przypadek, a może po prostu schemat działania narzędzi typu RAD zachęca do takiego pisania programów?

No właśnie. Filozofia narzędzia, która sie wpycha drzwiami i oknami - i tzw ekosystem, czyli miliony much, od których każdy nowy czerpie wzorce.
W szczególności użytkownik RAD nic nie czyta, w książkach mieszkają diabły a w ogóle książki są dla [----]

Ludzie są tak słabi, ze nie znają własnej biblioteki standardowej, masakryczne sumowanie słupków z pieniędzmi na double (ale z zaokragleniami, czyli coś świta!) - w kodzie sprzedawanym za ciężkie tysiace w ramach dużej firmy
Currency czy jaki tam był typ stałoprzecinkowy - nieznany.

0
AnyKtokolwiek napisał(a):

A jeśli porządny, posiadający architekturę kod jest przypadkiem, a spagetti na GUI statystyczną normą ?

No to powstrzymaj się od cherry pickingu i pokaż te badania statystyczne, najlepiej takie na bardzo dużej próbie, a wtedy pogadamy. Programiści, którzy bardzo dobrze znają daną technologię i potrafią w niej pisać bardzo dobry kod, nie są tymi, którzy zakładają wątki na 4programmers.

Ludzie są tak słabi, ze nie znają własnej biblioteki standardowej, masakryczne sumowanie słupków z pieniędzmi na double (ale z zaokragleniami, czyli coś świta!) - w kodzie sprzedawanym za ciężkie tysiace w ramach dużej firmy

O tym właśnie pisałem już wielokrotnie, również i w tym poście, który komentujesz. Wybieracie sobie losowy przypadek słabego kodu/kodera i przez jego pryzmat oceniacie całą technologię i wszystkich jej użytkowników. Smutne, że starasz się pisać z pozycji autorytetu, a jedyne na co cię stać to przebieranie w błędach poznawczych — nic tylko generalizacje i dowody anegdotyczne.

Currency czy jaki tam był typ stałoprzecinkowy - nieznany.

Dokumentacji użyj, nie szklanej kuli.

0

Ludzie są tak słabi, ze nie znają własnej biblioteki standardowej, masakryczne sumowanie słupków z pieniędzmi na double (ale z zaokragleniami, czyli coś świta!) - w kodzie sprzedawanym za ciężkie tysiace w ramach dużej firmy
Currency czy jaki tam był typ stałoprzecinkowy - nieznany.

Ale wiesz że Delphi źle zaokrągla polskie półgroszówki? Najpewniej dlatego ci starzy wyjadacze w dawnych czasach użyli niedostosowanych typów bo i tak nic to nie zmieniało a nawet przy być może ich lenistwie (czyli nie zadeklarowaniu lokalizacji aplikacji) wychodziłyby im kwiatki w stylu: na Windowsie w wersji angielskiej mieliby dolary lub funty.

1
furious programming napisał(a):

System komponentów wizualnych w Delphi, Lazarusie i innych narzędziach RAD jest tak zbudowany, aby kod obsługi tych komponentów był implementowany w zdarzeniach, których ciała generowane są automatycznie przez IDE. Jeśli chcesz oprogramować interakcję z kontrolką, uzupełniasz konkretne zdarzenie i koniec. Nieistotne jest to na ile metod podzielisz kod zdarzenia, ani czy skorzystasz z tego wygenerowanego czy podłączysz swoje z zewnątrz w runtime — całość sprowadza się do przewidzianego przez producenta zdarzenia kontrolki.

I tak samo jest np. w Unity

Koncept jest podobny, ale to nie to samo
Zrób coś takiego dla OnClicka w Delphi:

btn.onClick.AddListener(() => { EventManager.Broadcast<string, string>( EVNT.Button1, method, arguments); });

Dlaczego to nie to samo?
Bo mogę mieć wiele metod obsługi jednego zdarzenia i dodatkowo rozgłaszać je dalej.
I właśnie tego w Delphi brakuje by design.

— silnik zaprogramowany jest tak a nie inaczej, więc jego użytkownik korzysta z tego, co przygotowali jego twórcy (czyli konkretne klasy i metody). Nieistotne jest to, czy cały kod napiszesz w danej metodzie, czy podzielisz go na wiele metod, tak czy siak ta konkretna metoda silnika musi być wywołana. Możesz napisać w niej 1800 linii kodu, a możesz tylko jedną — z wywołaniem właściwej metody, zaimplementowanej gdzieś indziej.

Jednak dorobienie podobnego konceptu jak wyżej nie jest takie proste dla całego VCLa.
I to jest właśnie różnica, która ma znaczenie.

Tak więc to nie jest kwestia zachęcania czy nie, a architektury danej technologii. Natomiast zadaniem użytkownika jest dostosowanie się do specyfiki architektury i napisanie takiego kodu, aby dało się go wygodnie utrzymywać.

Przecież piszę od zawsze, że ta architektura jest cokolwiek sztywna...

0

@wloochacz: oczywiście, pełna zgoda. Zwróć jednak uwagę na to, że tutaj nie chodzi o to która architektura jest lepsza, a która gorsza, a o notoryczne twierdzenie, że samo istnienie systemu zdarzeń jest powodem istnienia słabej jakości kodu. Oczywiście, że takie twierdzenie jest bzdurą — bez względu na to czy mowa o Delphi, czy o C#, czy o jakiekolwiek inne technologie wykorzystujące system zdarzeń.

2
furious programming napisał(a):

@wloochacz: oczywiście, pełna zgoda. Zwróć jednak uwagę na to, że tutaj nie chodzi o to która architektura jest lepsza, a która gorsza, a o notoryczne twierdzenie, że samo istnienie systemu zdarzeń jest powodem istnienia słabej jakości kodu. Oczywiście, że takie twierdzenie jest bzdurą — bez względu na to czy mowa o Delphi, czy o C#, czy o jakiekolwiek inne technologie wykorzystujące system zdarzeń.

Ale wiesz (wiesz, prawda?) że w C# zdarzenia są obsługiwane przez delegaty by design właśnie?
To istotna przewaga.

Dwa - np. takie QT (czyli równie stare jak VCL) też (no oczywiście) ma zdarzenia, ale oparte o signal/slot typu multicast.
I znowu - to istotna przewaga.

Nie jestem pewien na 100%, ale chyba tylko VCL/FMX z dużych bibliotek UI nie ma zdarzeń typu multicast.

Dla mnie z kolei bzdurą (OK, przesadzam - to za mocne słowo. Tylko, że ja nie będę bronił konceptu nie do obrony.) jest ciągły brak czegoś podobnego do multicast events w Delphi.
I co ważne - zaimplementowane na poziomie RTL.

Ale..
Jasne, że wszystko zależy od programisty - na szczęście.
Paradoksalnie największym problemem jakości kodu w Delphi nie jest samo Delphi, a bajecznie prosty sposób tworzenia "jakoś" działających programów.
Przynajmniej na początku drogi z programowaniem 🙃
Osobiście uważam, że to z kolei implikuje iż "typowy programista Delphi" nie uczy się jak zrobić coś dobrze, tylko szuka "komponentów do klikania"...
A potem takie potworki jak ten wspomniany przez @Mr.YaHooo

Często potem jest już cholernie trudno to zrefaktoryzować i najczęściej jest to zadanie daleko poza zasięgiem "typowego programisty Delphi".

Na szczęście to się zmienia i dziś Delphi nie jest już tym samym Delphi co 10 i więcej lat temu.
I znowu - paradoksalnie to bardzo kurna dobrze dla samego Delphi 😉

PS.
Dlaczego uważam, że dzisiejsze Delphi to już nie to samo Delphi co kiedyś i to świetna wiadomość!
Pytanie takie; kto z Was słyszał o bibliotece FidoLib?
To bardzo ciekawy kod, coś zupełnie niespotykanego w świecie Delphi:
https://github.com/mirko-bianco/FidoLib/blob/develop/FidoCore.md

Właśnie dzięki rozwojowi możliwe są takie biblioteki.
Tylko co z tym zrobi "typowy programista Delphi"?

1
furious programming napisał(a):

I dlatego właśnie komponenty mają zdarzenia, bo są bardzo wygodne. :]

Jako ciekawostkę powiem, że miałem kilka podejść do Qt, chciałem rozpracować je do używania w pracy, ale... mechanizm slotów mnie jakoś nie przekonał. Klasyczne zdarzenia z biblioteki VCL są o wiele lepsze moim zdaniem :) Pytanie ile w tym przyzwyczajania.

grzegorz_so napisał(a):

Automat IDE działa tak jak działa.
Jeśli już mam potrzebę (albo chęć :) ) aby utworzyć formularz w IDE to w pierwszym kroku po utworzeniu nowej formy wywalam tę zmienną globalną

No i to jest wkurzające...

AnyKtokolwiek napisał(a):

A jeśli porządny, posiadający architekturę kod jest przypadkiem, a spagetti na GUI statystyczną normą ?
Jak ktos ma myślenie nie ustawione pod tezę, to mu to do myślenia daje.

Szczerze, to nie spotkałem jeszcze kodu który mógłbym uznać za ładnie zrobiony architektonicznie. Może jestem zbytnio perfekcyjny, albo co.

AnyKtokolwiek napisał(a):

No właśnie. Filozofia narzędzia, która sie wpycha drzwiami i oknami - i tzw ekosystem, czyli miliony much, od których każdy nowy czerpie wzorce.
W szczególności użytkownik RAD nic nie czyta, w książkach mieszkają diabły a w ogóle książki są dla [----]

Nie wiem czy tak jest, ale ja na szczęście pracuję z ludźmi którzy są jako-tako ogarnięci, a dobrą książką nie pogardzą :)

AnyKtokolwiek napisał(a):

Ludzie są tak słabi, ze nie znają własnej biblioteki standardowej, masakryczne sumowanie słupków z pieniędzmi na double (ale z zaokragleniami, czyli coś świta!) - w kodzie sprzedawanym za ciężkie tysiace w ramach dużej firmy
Currency czy jaki tam był typ stałoprzecinkowy - nieznany.

A to standard. Nie wiem skąd to wynika tylko.

furious programming napisał(a):

@wloochacz: oczywiście, pełna zgoda. Zwróć jednak uwagę na to, że tutaj nie chodzi o to która architektura jest lepsza, a która gorsza, a o notoryczne twierdzenie, że samo istnienie systemu zdarzeń jest powodem istnienia słabej jakości kodu. Oczywiście, że takie twierdzenie jest bzdurą — bez względu na to czy mowa o Delphi, czy o C#, czy o jakiekolwiek inne technologie wykorzystujące system zdarzeń.

Ależ ja niczego takiego nie twierdzę, sam napisałem w tym poście, że wolę zdarzenia z VCL'a niż sloty z Qt. Nie wiem czemu, ale mam wrażenie, że samo IDE skłania do upychania wszystkiego na formatkach. A wiem, bo sam od tego zaczynałem. Pierwsze moje projekty to był właśnie taki spaghetti, gdzie wszystko było upchnięte w zdarzeniach formatek. Dopiero jak mi się projekt rozrósł zobaczyłem, że to nie jest nic dobrego.

wloochacz napisał(a):

Ale..
Jasne, że wszystko zależy od programisty - na szczęście.
Paradoksalnie największym problemem jakości kodu w Delphi nie jest samo Delphi, a bajecznie prosty sposób tworzenia "jakoś" działających programów.
Przynajmniej na początku drogi z programowaniem 🙃
Osobiście uważam, że to z kolei implikuje iż "typowy programista Delphi" nie uczy się jak zrobić coś dobrze, tylko szuka "komponentów do klikania"...
A potem takie potworki jak ten wspomniany przez @Mr.YaHooo

I u chyba mamy clue problemu :)

wloochacz napisał(a):

Często potem jest już cholernie trudno to zrefaktoryzować i najczęściej jest to zadanie daleko poza zasięgiem "typowego programista Delphi".

Bardzo trudno, a ja mam poniekąd takie zadanie.

wloochacz napisał(a):

Dlaczego uważam, że dzisiejsze Delphi to już nie to samo Delphi co kiedyś i to świetna wiadomość?
Pytanie takie; kto z Was słyszał o bibliotece FidoLib?
To bardzo ciekawy kod, coś zupełnie niespotykanego w świecie Delphi:
https://github.com/mirko-bianco/FidoLib/blob/develop/FidoCore.md

Aż sobie poczytam w wolnej chwili :)

0

Nie wierzę Wam ani trochę, albo nie rozumiem problemu, jaki poniektórzy mają z Delphi.
A prawda jest taka, że narzędzie to umożliwia szybkie budowanie aplikacji, jest stosunkowo proste i zrozumiałe. Wciąż się rozwija (zapowiedziana jest wersja RAD 12).
Nie znam się na dużych projektach i w takowych z pewnością obowiązują standardy (hehe, takie jak zaprezentowano w Kato, gdzie nowy system obsługi pasażerów mówi wszystko o "profesjonalnych" programistach, to jest zazwyczaj leży i kwiczy). Ale do mniejszych nadaje się idealnie - i tak - to od programisty zależy w jaki sposób wykorzysta jego potencjał. Doświadczony programista napisze go tak, żeby kod był czytelny, można go było łatwo zmienić czy rozbudować, pracować grupowo, etc... amator nawali wszystko na głównej formie (też będzie działać... ale jak długo).

Nikt jednak z Was nie pokazał jaki to jest idealny projekt w Delphi... bez zmiennych globalnych, z wydzielonymi klasami i nie wiem czym jeszcze (bo ja się nie znam). Delphi jest tak skonstruowane i albo się dostosujemy albo może trzeba zmienić środowisko. A może napiszecie co komu przeszkadza zmienna globalna? Cóż to za wielkie przestępstwo zadeklarować zmienną w głównym module i użyć jej w innym? A co komu przeszkadza "system zdarzeń"? Przecież to uczyniło narzędzia typu Delphi tak popularnymi! Można szybko stworzyć aplikację, która realizuje co ma realizować.

2

to juz duży offtopic, ale jak sobie wyklikasz program w delphi i sprzedasz za milion baksów to wygrałeś.

Najczęściej jednak programy tworzy się zespołowo, dba o jakość, dba o pokrycie testami i inne rzeczy.

Delphi to szybkość tworzenia, ale statystycznie to też zmienne globalne, spaghetti, brak testów (a po co komu?).

Mało też kogo stać na ten RAD 12 - chyba że Community, no to okej amatorsko (zapewne z wadami jak wyżej).

0
lampasss napisał(a):

to juz duży offtopic, ale jak sobie wyklikasz program w delphi i sprzedasz za milion baksów to wygrałeś.

Najczęściej jednak programy tworzy się zespołowo, dba o jakość, dba o pokrycie testami i inne rzeczy.

Delphi to szybkość tworzenia, ale statystycznie to też zmienne globalne, spaghetti, brak testów (a po co komu?).

Dług techniczny już z chwilą wydania wersji alfa (jak odrzutowce wojskowe w latach 1950-1970)

Mało też kogo stać na ten RAD 12 - chyba że Community, no to okej amatorsko (zapewne z wadami jak wyżej).

Comunity chyba nadal ma zablokowany debuger ?
Miałem to g... z dawnego sentymentu z 4-5 lat temu

2
Pepe napisał(a):

Nie wierzę Wam ani trochę, albo nie rozumiem problemu, jaki poniektórzy mają z Delphi.

Żeby było jasne. Z Delphi nie mam problemu jako takiego. Uważam, że VCL jest przyjemniejszą biblioteką od Qt, czy technologii Microsoftowych. Jedynie do czego mam wątpliwości, to używanie mechanizmów RAD do większych projektów.

Pepe napisał(a):

A prawda jest taka, że narzędzie to umożliwia szybkie budowanie aplikacji, jest stosunkowo proste i zrozumiałe. Wciąż się rozwija (zapowiedziana jest wersja RAD 12).

Oczywiście, ale wraz ze wzrostem codebase'u rosną trudności w utrzymaniu ładnego i sensownego kodu.

Pepe napisał(a):

Nikt jednak z Was nie pokazał jaki to jest idealny projekt w Delphi... bez zmiennych globalnych, z wydzielonymi klasami i nie wiem czym jeszcze (bo ja się nie znam).

Ale coś takiego pokazać jest dość trudno. Wiadomo, że ideał nie istnieje ;)

Pepe napisał(a):

A może napiszecie co komu przeszkadza zmienna globalna?

  • Zmienną globalną można zmienić z każdego miejsca w każdym czasie, nawet przypadkowo, co może spowodować dziwne czasami ciężkie do wyłapania błędy. Dobrą zasadą jest jak najmniejszy zasięg zmiennych.
  • Co więcej wprowadzają niejawne zależności. Bez analizy całej funkcji, klasy nie jesteś w stanie powiedzieć czy dana funkcja/obiekt korzysta ze zmiennej.
  • Utrudniają pisanie testowalnego kodu.
  • Zaśmiecają globalną przestrzeń nazw która jest dostępna wszędzie. Co za tym idzie można przypadkowo zadeklarować dwie zmienne o tej samej nazwie, a wtedy będzie ciekawie.
  • Powodują problemy ze współbieżnością. Dostęp do zmiennej globalnej nie jest niczym sterowany i w przypadku korzystania i modyfikacji zmiennej przez różne wątki mogą błędy typu race condition.
Pepe napisał(a):

Cóż to za wielkie przestępstwo zadeklarować zmienną w głównym module i użyć jej w innym? A co komu przeszkadza "system zdarzeń"? Przecież to uczyniło narzędzia typu Delphi tak popularnymi! Można szybko stworzyć aplikację, która realizuje co ma realizować.

Ano można zabić w ten sposób pacjenta. Polecam poczytać o błędach w maszynie Therac-25 która na skutek błedu typu race condition który powodował podanie dawki promieniowania setki razy większych niż powinny pacjentom....

Natomiast jeśli chodzi o system sterowania zdarzeniami to jest to fana sprawa.

1
Mr.YaHooo napisał(a):

Oczywiście, ale wraz ze wzrostem codebase'u rosną trudności w utrzymaniu ładnego i sensownego kodu.

I wraz ze wzrostem liczby członków zespołu utrzymującego projekt. Jednak nadal nie zmienia to faktu, że to co piszesz nie jest domeną projektów stawianych w Delphi — to dotyczy dowolnego projektu i dowolnej technologii.

Pepe napisał(a):
  • Zmienną globalną można zmienić z każdego miejsca w każdym czasie, nawet przypadkowo, co może spowodować dziwne czasami ciężkie do wyłapania błędy. Dobrą zasadą jest jak najmniejszy zasięg zmiennych.

Pamiętaj jednak, że ta zmienna globalna jest domyślnie tworzona dla każdego formularza z konkretnego powodu. Ona musi być globalna, żeby IDE mogło w pliku .dpr zinstancjonować klasę formularza i zarejestrować ją w obiekcie aplikacji. Jeśli dany formularz ma nie być automatycznie tworzony przy rozruchu aplikacji, to ta zmienna nie jest potrzebna.

I nawet jeśli wyżej zacytowane słowa nie odnoszą się stricte do formularzy, to nadal niepoprawnym jest twierdzenie, że zmienne globalne to zło i nie powinny być w ogóle używane. One po to są globalne, aby właśnie były widoczne zewsząd, tak jak np. zmienna FormatSettings. Jeśli coś ma być globalne to się to robi globalne (unikając boilerplate'u), a jeśli dostęp ma być ograniczony, to się robi fasadę. Wszystko zależy od przypadku, nie od ludowych prawideł. ;)

  • Zaśmiecają globalną przestrzeń nazw która jest dostępna wszędzie. Co za tym idzie można przypadkowo zadeklarować dwie zmienne o tej samej nazwie, a wtedy będzie ciekawie.

Nie będzie ciekawie — albo dostaniesz błąd duplicate identifier, albo obie zmienne zostaną zadeklarowane poprawnie. Tutaj sprawa wygląda podobnie jak z każdym innym publicznym elementem modułu, więc to nie jest problem stricte zmiennych, a wszystkich elementów modułów (stałych, zmiennych, typów i subrutyn).

  • Powodują problemy ze współbieżnością. Dostęp do zmiennej globalnej nie jest niczym sterowany i w przypadku korzystania i modyfikacji zmiennej przez różne wątki mogą błędy typu race condition.

A co ze zmiennymi lokalnymi? Ich race condition nie dotyczy?

1
furious programming napisał(a):

I wraz ze wzrostem liczby członków zespołu utrzymującego projekt. Jednak nadal nie zmienia to faktu, że to co piszesz nie jest domeną projektów stawianych w Delphi — to dotyczy dowolnego projektu i dowolnej technologii.

Tak, dlatego twierdzę, że to wina programowania typu RAD. Co nie zmienia tego, że da się pisać sensownie w takim narzędziu.

furious programming napisał(a):

Pamiętaj jednak, że ta zmienna globalna jest domyślnie tworzona dla każdego formularza z konkretnego powodu. Ona musi być globalna, żeby IDE mogło w pliku .dpr zinstancjonować klasę formularza i zarejestrować ją w obiekcie aplikacji. Jeśli dany formularz ma nie być automatycznie tworzony przy rozruchu aplikacji, to ta zmienna nie jest potrzebna.

Tak, tak samo jak zmienne globalne są potrzebne IDE do tego, aby dało się podłączać zdarzenia, czy bindować kontrolki bazodanowe do komponentów z innych form. Jednak ja nigdy nie używam automatycznego tworzenia formularzy na starcie. Zawsze formularz tworzę dynamicznie przed jego pokazaniem. Co więcej plik główny zawiera tylko tworzenie mojego własnego obiektu w stylu TMySuperAppCore który to tworzy już wszystkie niezbędne obiekty i uruchamia całość aplikacji.

furious programming napisał(a):

I nawet jeśli wyżej zacytowane słowa nie odnoszą się stricte do formularzy, to nadal niepoprawnym jest twierdzenie, że zmienne globalne to zło i nie powinny być w ogóle używane. One po to są globalne, aby właśnie były widoczne zewsząd, tak jak np. zmienna FormatSettings. Jeśli coś ma być globalne to się to robi globalne (unikając boilerplate'u), a jeśli dostęp ma być ograniczony, to się robi fasadę. Wszystko zależy od przypadku, nie od ludowych prawideł. ;)

A jak wtedy przetestujesz taką funkcję? Tobi się trudniej. Zasadniczo masz rację, jednak dopuściłbym zmienne globalne w trybie tylko do odczytu. Chociaż wtedy i tak wolałbym wstrzyknąć parametr poprzez nową klasę, bo pewnie parametrów w aplikacji będzie więcej.

furious programming napisał(a):

Nie będzie ciekawie — albo dostaniesz błąd duplicate identifier, albo obie zmienne zostaną zadeklarowane poprawnie. Tutaj sprawa wygląda podobnie jak z każdym innym publicznym elementem modułu, więc to nie jest problem stricte zmiennych, a wszystkich elementów modułów (stałych, zmiennych, typów i subrutyn).

Tak, dlatego nie ma co zaśmiecać globalnych przestrzeni, zarówno funkcjami jak i zmiennymi. Dodatkowo w C/C++ można się nieźle nadziać w przypadku gdy mamy zmienną lokalną oraz globalną o tej samej nazwie.

furious programming napisał(a):

A co ze zmiennymi lokalnymi? Ich race condition nie dotyczy?

Raczej zmienna lokalna w funkcji nie będzie na to narażona, gdyż wtedy każdy wątek ma swoją własną kopię niezależną od innych.

1
Mr.YaHooo napisał(a):

Tak, dlatego twierdzę, że to wina programowania typu RAD. Co nie zmienia tego, że da się pisać sensownie w takim narzędziu.

Ciekawe czy piszesz tak dlatego, że faktycznie projekt ze zmiennymi globalnymi jest dla ciebie trudny do utrzymania, czy dlatego, że tak się utarło, że zmienne globalne to zło i koniec. Mam nadzieję, że to pierwsze. :]

Jednak ja nigdy nie używam automatycznego tworzenia formularzy na starcie. Zawsze formularz tworzę dynamicznie przed jego pokazaniem.

No to witaj w klubie. Ale ale — jeśli projekt jest mały, okienek kilka, to i można śmiało korzystać z automatu.

Co więcej plik główny zawiera tylko tworzenie mojego własnego obiektu w stylu TMySuperAppCore który to tworzy już wszystkie niezbędne obiekty i uruchamia całość aplikacji.

Brzmi jak God Object. Nie żebym mial coś przeciwko, ale… :D

Zasadniczo masz rację, jednak dopuściłbym zmienne globalne w trybie tylko do odczytu. Chociaż wtedy i tak wolałbym wstrzyknąć parametr poprzez nową klasę, bo pewnie parametrów w aplikacji będzie więcej.

Zależy od projektu. Ty piszesz w OOP, więc wstrzykiwania to pewnie korpo-norma (przerażają mnie te obiektowe cuda). Ja teraz robię w proceduralnym i jeśli potrzebuję, to deklaruję zmienne lokalne w sekcji implementation (lokalne dla modułu) i daję do nich publiczny, inline'owany getter (plus opcjonalnie setter). Czyli w sumie nie używam zmiennych globalnych w ogóle.

Dodatkowo w C/C++ można się nieźle nadziać w przypadku gdy mamy zmienną lokalną oraz globalną o tej samej nazwie.

Czemu? Zarówno w Pascalach jak i w C/C++ zachowanie w takim przypadku jest zdefinowane — wygrywa ta o mniejszym zasięgu. Najpierw poziom osadzenia (C/C++ lub nowe Delphi), potem zmienna lokalna, potem zmienna lokalna/globalna w module, potem zmienne globalne z innych modułów, wedle ich kolejności w uses.

Raczej zmienna lokalna w funkcji nie będzie na to narażona, gdyż wtedy każdy wątek ma swoją własną kopię niezależną od innych.

Nie mam na myśli zmiennej lokalnej dla funkcji wątku (bo każdy wątek miałby własną), a sytuację, w której dana funkcja tworzy i odpala wątki, które modyfikują zmienną lokalną funkcji wywołującej. Wtedy ta funkcja czeka aż wątki zakończą działanie i coś z tą zmienną lokalną dalej robi. Czyli de facto wątki modyfikują dane zmiennej w ramce stosu, nie w obrazie procesu.

0

Dziękuję za merytoryczne wypowiedzi! O to mi chodziło, żeby zainicjować dyskusję. Przecież właśnie dzięki forum i ludziom, którzy coś w życiu widzieli i napisali jakiś kawałek kodu, mniej zaawansowani, (tudzież amatorzy) mogą się coś nauczyć, zacząć stosować jakieś sensowne praktyki lub po prostu tworzyć lepszej jakości kod.

Jako amator, zasadniczo nie stosuję się do tych twierdzeń (proszę mnie jako takiego traktować - mimo, że w mojej opinii napisałem kilka super fajnych i przydatnych programów).
Jak tworzę program, to korzystam z formularzy - nie tworzę ich dynamicznie, bo po co (chyba że jest to konieczne, co czasem się zdarza). Zazwyczaj jednak, środowisko (IDE) załatwia za mnie "problemy" tworzenia okna i tysiące innych, o których nawet nie wiem, dzięki "automatowi". To dzięki RAD tworzenie aplikacji jest tak proste... przypomnę, że dobrych kilka lat temu, trzeba było korzystać z WinAPI, co myślę na pierwszy rzut oka odrzucało każdego - składnia skomplikowana, dziwne nazwy, wszystko trzeba było pisać samemu... a teraz? Niebo a ziemia. Nakładanie na siebie kagańca i szukanie trudnych i pracochłonnych rozwiązań jest bezsensowne. Wystarczy z głową korzystać z rozwiązań, które oferuje środowisko... Ale z drugiej strony, nie jest tak, że człowiek nawali formatek, cały kod pisany w zdarzeniach kontrolek, bez składu i ładu... może tak się robi pod presją czasu w korpo, ale jak ktoś koduje dla siebie to wydaje mi się, że dba o to co pisze - jeśli tylko wie co robi. Z pewnością nie jest to kod książkowy, ale działa i wbrew opinii niektórych, można go rozwijać.

Tak samo, nie boję się użyć zmiennych globalnych, bo wiem co robię, odpowiednio je nazywam i nie ma opcji, żebym spowodował problemy. Przypominam - nie piszę bardzo dużych i skomplikowanych projektów. Pewnie takowe wymuszają inne podejście (z tym nie będę polemizował - duży projekt, skalowalny to inna bajka) - być może warto użyć innego narzędzia, a nie psioczyć na RAD. Poza tym, zmienne globalne (jak już przy nich jesteśmy) istnieją nie po to, żeby istnieć tylko żeby ich używać.

0
furious programming napisał(a):

Ciekawe czy piszesz tak dlatego, że faktycznie projekt ze zmiennymi globalnymi jest dla ciebie trudny do utrzymania, czy dlatego, że tak się utarło, że zmienne globalne to zło i koniec. Mam nadzieję, że to pierwsze. :]

Nigdy nie piszę czegoś, bo tak wypada ;) Jak tak piszę, to uważam :)

furious programming napisał(a):

No to witaj w klubie. Ale ale — jeśli projekt jest mały, okienek kilka, to i można śmiało korzystać z automatu.

Oczywiście, kwestia w jakiej skali działamy :)

furious programming napisał(a):

Brzmi jak God Object. Nie żebym mial coś przeciwko, ale… :D

Bo to jest swego rodzaju God Object :D Ale, coś musi wykonać robotę polegającą na wczytaniu konfigów, połączeniu z bazą danych, wyświetleniem okien ewentualnych błędów, czy też zalogowaniem użytkownika. Po poprawnym logowaniu uruchamia niezbędne moduły. Chociaż z drugiej strony taki VCL też ma podobny obiekt inicjujący TApplication Tam zapewne jest jeszcze więcej roboty :)

furious programming napisał(a):

Zależy od projektu. Ty piszesz w OOP, więc wstrzykiwania to pewnie korpo-norma (przerażają mnie te obiektowe cuda). Ja teraz robię w proceduralnym i jeśli potrzebuję, to deklaruję zmienne lokalne w sekcji implementation (lokalne dla modułu) i daję do nich publiczny, inline'owany getter (plus opcjonalnie setter). Czyli w sumie nie używam zmiennych globalnych w ogóle.

Nie jest to takie czyste OOP z interfejsami ko którym wszystko dziedziczy. Ot jest ok 40 modułów i jeden AppCore który to ma w sobie połączenie do bazy, ustawienia systemu typu format daty itp. Osobiście nie trawię Javy gdzie wszystko dziedziczy po wszystkim i czasami ciężko jest dość co do czego.

furious programming napisał(a):

Czemu? Zarówno w Pascalach jak i w C/C++ zachowanie w takim przypadku jest zdefinowane — wygrywa ta o mniejszym zasięgu. Najpierw poziom osadzenia (C/C++ lub nowe Delphi), potem zmienna lokalna, potem zmienna lokalna/globalna w module, potem zmienne globalne z innych modułów, wedle ich kolejności w uses.

Na początku, jak jeszcze używałem globali zdarzało mi się pomylić zmienną globalną z lokalną i wtedy była zabawa. Wiadomo, że wygrywa zmienna o mniejszym zasięgu, ale to jest kolejna zasada jaką należy pamiętać, a chciałbym idealnie mieć wyeliminowaną potrzebę pamiętania takich rzeczy. Po prostu nie wierzę sam sobie i eliminuję wszelkie wektory pomyłek.

furious programming napisał(a):

Nie mam na myśli zmiennej lokalnej dla funkcji wątku (bo każdy wątek miałby własną), a sytuację, w której dana funkcja tworzy i odpala wątki, które modyfikują zmienną lokalną funkcji wywołującej. Wtedy ta funkcja czeka aż wątku zakończą działanie i coś z tą zmienną lokalną dalej robi. Czyli de facto wątki modyfikują dane zmiennej w ramce stosu, nie w obrazie procesu.

Ok, to wtedy racja. Wtedy jednak to funkcja wywołująca ma za zadanie czekać i odpowiednio zarządzać zmienną. Chyba, że owa zmienna jest potrzebna również w innych wątkach. Wtedy robi się bardziej skomplikowanie.

Pepe napisał(a):

Dziękuję za merytoryczne wypowiedzi! O to mi chodziło, żeby zainicjować dyskusję. Przecież właśnie dzięki forum i ludziom, którzy coś w życiu widzieli i napisali jakiś kawałek kodu, mniej zaawansowani, (tudzież amatorzy) mogą się coś nauczyć, zacząć stosować jakieś sensowne praktyki lub po prostu tworzyć lepszej jakości kod.

Dokładnie też tak myślę, zawsze warto poczytać co inni mają do powiedzenia na dany temat.

Pepe napisał(a):

Jako amator, zasadniczo nie stosuję się do tych twierdzeń (proszę mnie jako takiego traktować - mimo, że w mojej opinii napisałem kilka super fajnych i przydatnych programów).
Jak tworzę program, to korzystam z formularzy - nie tworzę ich dynamicznie, bo po co (chyba że jest to konieczne, co czasem się zdarza). Zazwyczaj jednak, środowisko (IDE) załatwia za mnie "problemy" tworzenia okna i tysiące innych, o których nawet nie wiem, dzięki "automatowi". To dzięki RAD tworzenie aplikacji jest tak proste... przypomnę, że dobrych kilka lat temu, trzeba było korzystać z WinAPI, co myślę na pierwszy rzut oka odrzucało każdego - składnia skomplikowana, dziwne nazwy, wszystko trzeba było pisać samemu... a teraz? Niebo a ziemia. Nakładanie na siebie kagańca i szukanie trudnych i pracochłonnych rozwiązań jest bezsensowne. Wystarczy z głową korzystać z rozwiązań, które oferuje środowisko... Ale z drugiej strony, nie jest tak, że człowiek nawali formatek, cały kod pisany w zdarzeniach kontrolek, bez składu i ładu... może tak się robi pod presją czasu w korpo, ale jak ktoś koduje dla siebie to wydaje mi się, że dba o to co pisze - jeśli tylko wie co robi. Z pewnością nie jest to kod książkowy, ale działa i wbrew opinii niektórych, można go rozwijać.

Tak, tak samo jak nikt nie pisze już w assemblerze, tylko w językach wyższego poziomu. Co prawda sam zaczynałem od WinAPI i doskonale wiem jaką robotę odwala za nas każda biblioteka typu VCL, Qt czy też .Net Nie wyobrażam sobie pisać coś w WinAPI więcej niż proste crackme...
Żeby nie było, że jestem idealny. Jednak sam też popełniam od czasu do czasu program gdzie wszystko leży na formatkach i IDE tworzy za mnie wszystko. Z reguły są to proste narzędzia wspomagające pracę wdrożeniowców systemu, a i popełniłem tak kilka prostych programów pomocniczych na zasadzie raz zakoduj, zainstaluj, użytkownik używa tego już 8 lat bez żadnej zmiany :)

Pepe napisał(a):

Tak samo, nie boję się użyć zmiennych globalnych, bo wiem co robię, odpowiednio je nazywam i nie ma opcji, żebym spowodował problemy. Przypominam - nie piszę bardzo dużych i skomplikowanych projektów. Pewnie takowe wymuszają inne podejście (z tym nie będę polemizował - duży projekt, skalowalny to inna bajka) - być może warto użyć innego narzędzia, a nie psioczyć na RAD. Poza tym, zmienne globalne (jak już przy nich jesteśmy) istnieją nie po to, żeby istnieć tylko żeby ich używać.

O ile wiesz co robisz, to jak najbardziej. Jeśli się samemu trzyma jakiejś konwencji to bardzo dobrze. Nawet jeśli jest ona dziwaczna. Ważne, aby robić to konsekwentnie. Przypomina mi się tu jednak dyskusja na temat goto która też wywołuje zażarte dyskusje.

0
Mr.YaHooo napisał(a):

Bo to jest swego rodzaju God Object :D Ale, coś musi wykonać robotę polegającą na wczytaniu konfigów, połączeniu z bazą danych, wyświetleniem okien ewentualnych błędów, czy też zalogowaniem użytkownika. Po poprawnym logowaniu uruchamia niezbędne moduły.

Czyli to nie jest God Object, a coś w rodzaju menedżera modułów.

Coś podobnego robiłem dla swojej poprzedniej gry — klasa TGame, która odpowiada za zarządzanie instancjami modułów (klas) gry i wykonywanie metod najwyższego rzędu. Każdy moduł gry posiada zmienną globalną (tak jak zmienne z formularzami), więc można się do nich dostać z dowolnego miejsca w kodzie.

Innym razem (w platformerze) poszedłem o krok dalej i taka główna klasa nie tylko zarządzała zasobami, ale też dawała dostęp do wszystkich modułów gry, udostępniając singletony w swoich właściwościach. Taki God Object był w zmiennej globalnej i był czymś w rodzaju hubu. Dzięki temu z dowolnego miejsca w kodzie można było odwoływać się do dowolnego modułu gry, właśnie poprzez ten obiekt-hub. Problemy z modularyzacją i błędami circular reference zażegnane bezpowrotnie.

Ok, to wtedy racja. Wtedy jednak to funkcja wywołująca ma za zadanie czekać i odpowiednio zarządzać zmienną. Chyba, że owa zmienna jest potrzebna również w innych wątkach. Wtedy robi się bardziej skomplikowanie.

Tutaj jest to typowy problem synchronizacji wątków i współdzielenia zasobów, dlatego pisałem, że nie ma znaczenia czy to zmienna globalna czy lokalna. Problemu nie będzie tylko w przypadku threadvarów i lokalnych zmiennych w ciałach funkcji wątków, bo synchronizacja nie jest wymagana.

O ile wiesz co robisz, to jak najbardziej. Jeśli się samemu trzyma jakiejś konwencji to bardzo dobrze. Nawet jeśli jest ona dziwaczna. Ważne, aby robić to konsekwentnie.

Szczególnie, jeśli ma się ten luksus tworzenia źródeł w pojedynkę.

Przypomina mi się tu jednak dyskusja na temat goto która też wywołuje zażarte dyskusje.

Kilka dni temu natknąłem się na film Never nester, czyli o tym, że nadmierne zagnieżdżanie ifów jest złe i że lepiej zrobić wczesne returny. Podejście jak najbardziej logiczne i doceniane. Robię dokładnie to samo, tyle że zamiast return skaczę do końcowego cleanupu za pomocą goto — no i burza, bo goto to przeciez zło.

Rzeźbienie w pojedynkę daje wolność i święty spokój, co nie @Pepe? :]

0

@furious programming: Zdecydowanie tak! :)

0
furious programming napisał(a):

Czyli to nie jest God Object, a coś w rodzaju menedżera modułów.

W sumie podobne. Jednak były głosy, żeby z tego zrezygnować bo się komuś nie podobało. Nie odpuściłem i dalej to trzymam.

furious programming napisał(a):

Coś podobnego robiłem dla swojej poprzedniej gry — klasa TGame, która odpowiada za zarządzanie instancjami modułów (klas) gry i wykonywanie metod najwyższego rzędu. Każdy moduł gry posiada zmienną globalną (tak jak zmienne z formularzami), więc można się do nich dostać z dowolnego miejsca w kodzie.

Bardzo mi się to podoba, dobrze zrobione :)

furious programming napisał(a):

Innym razem (w platformerze) poszedłem o krok dalej i taka główna klasa nie tylko zarządzała zasobami, ale też dawała dostęp do wszystkich modułów gry, udostępniając singletony w swoich właściwościach. Taki God Object był w zmiennej globalnej i był czymś w rodzaju hubu. Dzięki temu z dowolnego miejsca w kodzie można było odwoływać się do dowolnego modułu gry, właśnie poprzez ten obiekt-hub. Problemy z modularyzacją i błędami circular reference zażegnane bezpowrotnie.

Też niezłe rozwiązanie, takie zmienne globalne to ja rozumiem :) A circular reference to swego czasu u siebie często napotykałem...

furious programming napisał(a):

Szczególnie, jeśli ma się ten luksus tworzenia źródeł w pojedynkę.

Wtedy to panuje pełna dowolność. Gorzej jak się trafi w zespole beton który programował za czasów DOS'a (lub wcześniejszych) i on nie będzie tego robił w zaproponowany przeze mnie sposób, bo jego sposób jest lepszy, bo pisze już tak 30 lat :D

furious programming napisał(a):

Kilka dni temu natknąłem się na film Never nester, czyli o tym, że nadmierne zagnieżdżanie ifów jest złe i że lepiej zrobić wczesne returny. Podejście jak najbardziej logiczne i doceniane. Robię dokładnie to samo, tyle że zamiast return skaczę do końcowego cleanupu za pomocą goto — no i burza, bo goto to przeciez zło.

Oj tak, zagnieżdżone if'y to zło. Czasamii takich warunków jest tyle, że nie idzie tego zrozumieć. Dlatego w takich przypadkach jak opisujesz, to użycie goto jest moim zdaniem sensowne. Oczywiście można robić jakieś zmienne logiczne po to aby omijać kolejne bloki kodu, można duplikować kod sprzątający. Ale to bez sensu skoro można coś zrobić prościej.

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