[C++] Określić słabe punkty gotowego programu

0

Nie wiedziałem, jak sformułować temat...

Napisałem program (BCB 6.0, ok.200 kb bardzo dobrze komentowanego kodu), który chciałbym udostępnić na licencji GNU jako Open Source. Ale tego nie zrobię, bo się wstydzę. Program działa, ale w środku jest groch z kapustą. Chciałbym go przepisać od nowa, albo ulepszyć jego kod. Rozwijałem go dwa lata.

No i zobaczyłem, że w temacie http://4programmers.net/Forum/viewtopic.php?id=123187
użytkownik o nicku cyriel napisał tak:
"Jeśli stworzysz już jakieś zabezpieczenie to wrzuć je na forum - jak "przetrzyma" ponad tydzień to znaczy, że jest wystarczająco dobre - wystarczy"

To podsunęło mi pewną myśl. Otóż ja nie jestem i nie będę zawodowym programistą i nie chcę żadnych pieniędzy, ale też nie chciałbym, by dwuletni trud poszedł na marne. Pomyślałem, że może jest na forum jakiś dobrowolny twardziel, który zajrzałby do kodu tego mojego programu i powytykał mi jakieś błędy.

Nie szukam bugów, zakładam, że program działa. Tylko chodzi o to, jak jest napisany, a nie wiem, jak zrobić to lepiej

Źródła mogę podesłać, to żadna tajemnica. Tylko chodzi mi o to, czy w ogóle to ma jakiekolwiek szanse powodzenia. Wiem, że tu jest dużo ludzi, ale każdy ma rodzinę, pracę, znajomych, czas wolny, swoje kłopoty... a mój program nie jest mały.

[[[Tu jeszcze małe wyjaśnienie:
Nie chodzi mi o to, żeby ktoś za mnie wykonał robotę, tylko o to, że ja sam nie wiem, co robić i jak robić. Skoro może się znaleźć ktoś, kto przetestuje zabezpieczenie programu, to może się znajdzie ktoś, kto zerknie do źródeł (choć to mniej ekscytujące) ??? ]]]

0

No to dawaj linka do prog+źródła , powinien już być w pierwszym poście .
{może trochę więcej info. do czego jest ten prog}
Jak komuś przyjdzie ochota to zerknie...

0

[[[Tu jeszcze małe wyjaśnienie:
Nie chodzi mi o to, żeby ktoś za mnie wykonał robotę, tylko o to, że ja sam nie wiem, co robić i jak robić. Skoro może się znaleźć ktoś, kto przetestuje zabezpieczenie programu, to może się znajdzie ktoś, kto zerknie do źródeł (choć to mniej ekscytujące) ??? ]]]

Ooooooo. wreszcie jakaś miła odmiana po ciągłym "nie umiem, nie chce umieć, potrzebuje na wczoraj, zróbcie za mnie" :)

Przyłączam się do postu wyżej

0

http://www.wrzucaj.com/203719

tam jest plik exe, źródła (cpp, h), pliki związane z projektem Borland Buildera (bpr, dfm i inne takie) oraz plik konfiguracyjny.

W zasadzie wszystko, żeby każdy mógł skompilować to u siebie w domu.

Program jest ...

kalkulatorem

i teraz każdy powinien wydać westchnienie... :)

Na co dzień rysuję w AutoCAD-zie i potrzebny był mi podręczny, prosty i wygodny kalkulator, który potrafi liczyć dokładnie, a jednocześnie nie zajmuje w ogóle miejsca. No i napisałem Qualc, który zajmuje dwie linijki tekstu długie na kilka cm, ale w środku ma skomplikowaną maszynerię.

Obsługuje 4 podstawowe działania i nawiasy oraz traktuje literkę "A" jako ostatni wynik

Nie posiada menu (miejsce) ale ma graficzne menu kontekstowe w polu Edit (i tylko w nim!)

Nie posiada paska tytułu (miejsce) ale można go włączyć. Nie jest jednak potrzebny, bo program można przesuwać chwytając go za przycisk w lewym dolnym rogu.

Nie posiada klawiatury, ale można ją włączyć z menu kontekstowego (no ale po co, skoro jest key pad?).

Pilnowałem, by działał na Win98, 2000, XP (nie wiem, co z NT, 95 i Vistą) oraz pod linuksem w WINE (ale tam kolorowanie wyniku klęka)

W programowaniu nie używam w ogóle dziedziczenia - tylko agregaty (obiekt w obiekcie).

Kalkulator stwarza na moment obliczeń coś w rodzaju maszyny do odwrotnej notacji polskiej, która działa na moich liczbach. Sposób ich działania wymyśliłem sam i pisałem samodzielnie, ale okazało się, że inny gość zrobił już coś podobnego (zrobił to lepiej, szybciej i czyściej, ale nie do końca tak, jak ja potrzebowałem) i posiłkowałem się jego kodem (nawet do niego pisałem, ale nie odpowiedział).

Generalnie to było dawno temu, z resztą nie widzę potrzeby dodawania nowych funkcji (sinusy, cosinusy, pierwiastki), natomiast z chęcią bym rozwinął swoje umiejętności czystej (lub chociaż trochę czystszej) implementacji, czyli przerobił to co jest do postaci cywilizowanej. Najbardziej śmieszny i nieporadny jest moduł Robot, no ale może nie będę sam komentował, skoro każdy sam to dojrzy.

Generalny mój problem a propos GUI polega na nieumiejętności unikania pisania tego samego po raz drugi (preprocesor odpada; pisanie zewnętrznych funkcji usługowych uzależnia obiekty od tych funkcji... a nie pisanie ich - to wielokrotne dublowanie się). Albo np. kawałki kodu różniące się tylko plusem i minusem... ehhh

Jeśli kto ma czas, to zapraszam, a przy okazji - program działa i można używać, kopiować itd, byle pamiętać, że to GNU

p.s. napisanie części liczącej (Qualclass, Liczba) trwało co najmniej 800 godzin (prawie 3 miesiące od rana do wieczora), każda linijka była testowana. CodeWatch pokazuje kilka ostrzeżeń o wskaźniku poza zakresem, ale jestem pewien, że działa jak powinno. Po prostu używam tych wskaźników nietypowo, ale to akurat jest zaszyte zbyt głęboko, by to zmienić, a aż tyle czasu już nie mam. Ale bliżej powierzchni jest dużo kwiatków, którymi można się zająć

0

Przyjrzałem się klasie Qualclass, cieknie z niej w przypadku wpisania złej formuły. Metoda Przetwarzaj to jakiś koszmar - ~700 linii na jedną funkcję to chyba trochę za dużo. No i formatowanie... ciężko się to czyta.

0

Na pierwszy rzut oka:

Dlaczego, jak klikam w zielony przycisk nic sie nie dzieje ? Jeśli akcja jest niedostępna to przycisk też powinien być niedostępny.

Co z potęgowaniem i logarytmami, funkcjami trygonometrycznymi, w ogóle jakimiś funkcjami ? Bez tego program nie ma szans w śród masy darmowej konkurencji.

Przydała by się możliwość deklarowania zmiennych.

robotsmieci.h:
Mnóstwo metod które robią to samo. A wystarczą 3.

case 1: ... case 2: ... case 3: ... case 50: ... w mordę 2 lata programujesz, a jeszcze się z tablic nie nauczyłeś korzystać ? Większości tych switch'ów powinno nie być.

Oddziel metody zajmujące się interfejsem użytkownika od metod zajmujących się liczeniem poprzez umieszczenie ich w oddzielnych cpp. W ogóle tych .cpp powinieneś mieć 4 razy więcej.

W plikach nagłówkowych .h powinny być ... nagłówki :). Ciała metod przenieś do plików .cpp.

0

@ 0x666:

Przyjrzałem się klasie Qualclass, cieknie z niej w przypadku wpisania złej formuły.

Już nad tym siedzę. Faktycznie, trochę beztrosko to było zrobione. W wypadku jakiegokolwiek błędu tylko return i wyciek minimum 150 bajtów... Poprawiam.

Metoda Przetwarzaj to jakiś koszmar

Też już do tego doszedłem. Ale spróbuję to jakos podzielić.

No i formatowanie... ciężko się to czyta.

piszę w stylu EMACS i do niczego innego nie umiałem się przyzwyczaić. Mam problemy z koncentracją i muszę widzieć wszystkie nawiasy, albo się w nich zaraz gubię ;) To jest też powód, dla jakiego muszę pisać za nawiasami klamrowymi, co zamykają. A wystarczyło by, gdyby edytor jakoś oznaczał nawiasy...

@ adf88:

Dlaczego, jak klikam w zielony przycisk nic sie nie dzieje ? Jeśli akcja jest niedostępna to przycisk też powinien być niedostępny.

Bo to jest kontrolka statusu. Kiedy jest zielona, to znaczy, że z program czeka. W przypadku długotrwałych obliczeń (np. ostrego potęgowania) zamienia się na coś, co pokazuje, że program jeszcze żyje (animowana klepsydra z kursorów XFree)

Co z potęgowaniem i logarytmami, funkcjami trygonometrycznymi, w ogóle jakimiś funkcjami ? Bez tego program nie ma szans w śród masy darmowej konkurencji.
Przydała by się możliwość deklarowania zmiennych.

To są tzw. feature requests. Są na nie miejsca w programie przygotowane, czekające na wypełnienie. Ale jakoś nie mam siły na to na razie. Konkurencja jest ogromna więc i tak nie mam szans w sensie matematycznym, zatem postawiłem na wygodę i minimalizm.

robotsmieci.h:
Mnóstwo metod które robią to samo. A wystarczą 3.

case 1: ... case 2: ... case 3: ... case 50: ... w mordę 2 lata programujesz, a jeszcze się z tablic nie nauczyłeś korzystać ? Większości tych switch'ów powinno nie być.

Tam jest prawdziwa masakra :) Cały "Robot" to jedno wielkie badziewie. Tyle, że działa.

Oddziel metody zajmujące się interfejsem użytkownika od metod zajmujących się liczeniem poprzez umieszczenie ich w oddzielnych cpp. W ogóle tych .cpp powinieneś mieć 4 razy więcej.

Przyznam się, że właśnie z tym mam największe kłopoty, jeśli chodzi o C++. Zdarzało mi się już dziesiątki razy, że nie umiałem czegoś rozdzielić na dwa pliki. Wiem, że to zupełne podstawy, dlatego też właśnie postanowiłem do nich wrócić. Rozdział interfejsu od reszty to dla mnie ból, jakich mało

W plikach nagłówkowych .h powinny być ... nagłówki :). Ciała metod przenieś do plików .cpp.

To znaczy jak? Do .h dać tylko deklaracje, a wszystko w .cpp ? Ale to mi nie wyjdzie na to samo? A będę miał dwa pliki, zamiast jednego, czyli jeszcze większy bajzel, niż już zrobiłem.

Mój styl (a w zasadzie brak stylu) nie wziął się z niczego... Uczyłem się programować sam i nigdy nie miałem żadnego znajomego programisty. Potem przez 9 lat nie miałem komputera i pisałem tylko algorytmy/procedury w pseudokodzie. Teraz od paru lat znów mogę pisać, ale za to od roku nie mam czasu. I wychodzi to dość okropnie ;)
Nigdy nie widziałem źródeł porządnie napisanego programu, bo albo po ich rozpakowaniu stwierdzam, że ich w ogóle nie rozumiem (Firefox) albo dotyczą czegoś, co jest poza moim poziomem pojmowania (emule). Poza tym nie rozumiem zupełnie, jak działają interfejsy tych programów.

Wracając do kalkulatora... Badziewny, ale działa i do moich zastosowań wystarcza. Chciałbym go kiedyś wrzucić na sourceforge, ale w obecnym stanie jest się czego wstydzić i chcę go poprawić. Jak się uda, to z Waszą pomocą. Ewentualnie rozwinąć, ale ewolucja dopiero po uzyskaniu sensownej platformy wyjściowej. Na pewno nie mogę zacząć tego pisać od zera, więc albo poprawię to co jest, albo nic z tego nie będzie.

Jak na razie dzięki za komentarze. Uaktualnioną wersję wrzucę, jak będzie co pokazać, ale nie wiem, czy dzisiaj.

0

http://www.wrzucaj.com/651697

po modyfikacji (Qualclass już dealokuje pamięć przy błędzie, Kalkulator (na razie tylko on, bo to wprawka) został rozdzielony na .h i .cpp)

Wrzucam, by pokazać, że nie siedzę z założonymi rękami, ale prawdę powiedziawszy, potrzebny mi dokształt: muszę się po raz 10. nauczyć tego, co już 9 razy wiedziałem :(

Po tylu latach wciąż nie umiem dzielić kodu na osobne pliki. Problemem jest właśnie agregacja: jeśli X zawiera się w Y, Y zawiera się w Z, to w każdym pliku nagłówkowym tych obiektów będzie #include do wszystkich trzech (przynajmniej u mnie tak jest) i wtedy dochodzę do błędu:

[Linker warning] Public symbol <_cos-tam> defined in both module <cos-tam.obj> and <cos-tam.obj>

:(
Wiedzę się albo ma albo nie, ale ja mam mieć. Kwestia czasu i pokażę coś więcej. Na razie biorę książkę, całkiem serio.

0

No już lepiej jeśli chodzi o wycieki. W sumie mogłeś te wszystkie alokacje i zabawy na wskaźnikach zamienić vectorami. Pozbyłbyś się takich wiązanek:

delete [] typ; delete [] poct; delete [] konc;
// i
ZwolnijPamiec (typ, poct, konc, WskDoLiczb, iletok)

Nie wiem po co to?

int& prec = Liczba::RefPrecyzja();         
bool& grup = Liczba::RefGrupowanie();
bool& okrag = Liczba::RefZaokraglanie();
char& septor = Liczba::RefSeparator();

tylko zaciemnia kod.

class Qualclass
{
public:
    [...]

   Liczba Przetwarzaj (char *ZawartoscEdit, int stringdlg, int & Error);
   void ZwolnijPamiec (char * typ, int * poct, int * konc, Liczba ** WskDoLiczb, int iletok);
   bool Qualclass::CzyOperator (char token);
   int Qualclass::Priorytet( char oper);
   inline bool CzyLiczba(char token);         // L, A, N
};

ZwolnijPamiec, CzyOperator, Priorytet i CzyLiczba publiczne raczej być nie powinny.

Dlaczego funkcje

int ChceMiecLiczbeWEdit (TEdit *okno, char *tekst, int dluzyzna);
int ChceMiecIntWEdit (TEdit *okno, char *tekst, int dluzyzna);

int nwd(int a, int b);
int jednosci (int& licz, int& mian, int& jedn);
int skroc (int& licz, int& mian, int& jedn, int PostacUlamka, int Mrugaj);
int WykonajSkracanie();

nie są metodami klasy TRobot?

0
0x666 napisał(a)

Nie wiem po co to?

int& prec = Liczba::RefPrecyzja();         
bool& grup = Liczba::RefGrupowanie();
bool& okrag = Liczba::RefZaokraglanie();
char& septor = Liczba::RefSeparator();

tylko zaciemnia kod.

o ile dobrze pamiętam, zrobiłem tak, bo pomyślałem, że gdyby user zmienił preferencje podczas długotrwałych obliczeń, to skończyłoby się to małą katastrofą. Te zmienne miały być warstwą pośrednią między panelem ustawień, a wewnętrzną maszynerią kalkulatora. Ale też mi się to nie podoba.

Na razie rozdzielam kod na nagłówki i .cpp i idzie to w strasznych bólach

//zbliża się poniedziałek... :/
Na razie rozdzieliłem klasę Qualclass na nagłówek i .cpp ale to pociągnęło dużo komplikacji. Największa z nich: funkcje (metody) inline (a mam ich sporo) nie mogą być w .cpp więc i tak część metod będzie w .h .
Można by nawet pokasować żądania inline i nawet może .exe by się zmniejszył, ale to ma być szybkie, a nie niewielkie.

Mam nadzieję w pon. lub wt. wrzucić kolejne stadium.

0

o ile dobrze pamiętam, zrobiłem tak, bo pomyślałem, że gdyby user zmienił preferencje podczas długotrwałych obliczeń, to skończyłoby się to małą katastrofą.

Ten zabieg i tak niczego nie zmienia ;)

Na razie rozdzieliłem klasę Qualclass na nagłówek i .cpp ale to pociągnęło dużo komplikacji. Największa z nich: funkcje (metody) inline (a mam ich sporo) nie mogą być w .cpp więc i tak część metod będzie w .h .

Nie ma konieczności przenoszenia implementacji wszystkich metod do pliku cpp. Jeśli metoda jest mała, może być w całości zdefiniowana w pliku nagłówkowym.

0
0x666 napisał(a)

No już lepiej jeśli chodzi o wycieki. W sumie mogłeś te wszystkie alokacje i zabawy na wskaźnikach zamienić vectorami. Pozbyłbyś się takich wiązanek:

delete [] typ; delete [] poct; delete [] konc;
// i
ZwolnijPamiec (typ, poct, konc, WskDoLiczb, iletok)

Silnik programu (3 najgłębsze klasy: Qualclass, Liczba, segmenty) powstawał jako praca dyplomowa (nie magisterska) i to musiało działać. Dlatego poświęciłem temu tyle czasu. Interfejs już w pierwowzorze był nietypowy, ale obecna forma jest całkowitą przebudową.
A że nie potrafiłem (i nadal nie potrafię) w BCB debugować kontenerów, więc wskaźniki były bezpieczniejsze. Umiałem je śledzić krok po kroku. Chodzi o to, że nie mogłem iść dalej nie mając pewności, że wcześniejsza część kodu jest ok - to dawało mi poczucie pewności, że jak jest błąd, to zawsze w nowej partii kodu.

Obecnie dzielę kalkulator (Qualclass::Przetwarzaj.....) na mniejsze kawałki, żeby stał się tylko skorupą, która przygotowuje obiekt do działania i wywołuje prywatne metody, w których będą kawałki tego, co obecnie jest jednym ciągiem tych 700 linii :)

Jeśli się uda, wrzucę jeszcze dziś nową wersję.

0x666 napisał(a)

Dlaczego funkcje

int ChceMiecLiczbeWEdit (TEdit *okno, char *tekst, int dluzyzna);
int ChceMiecIntWEdit (TEdit *okno, char *tekst, int dluzyzna);

int nwd(int a, int b);
int jednosci (int& licz, int& mian, int& jedn);
int skroc (int& licz, int& mian, int& jedn, int PostacUlamka, int Mrugaj);
int WykonajSkracanie();

nie są metodami klasy TRobot?

Robotem się zajmę osobno w wolnej chwili :)

0

Qualclass::Przetwarzaj pocięty już na kawałki. W dalszej kolejności owe kawałki chcę nieco od siebie odseparować (bo na razie one nic jawnie nie przyjmują i nic nie zwracają). Niby Pikuś, a robiłem to kupę czasu, wczoraj i dziś, bo 3 razy musiałem się cofać do punktu wyjścia.

"Kawałki" stały sie metodami prywatnymi i całym zsypem prywatnych właściwości klasy Qualclass. Chyba zrobiło się nieco przejrzyściej, ale jeszcze długa droga.

http://www.wrzucaj.com/239783

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