O co chodzi z tym całym polimorfizmem?

0

właśnie przeczytałem ten: http://www.cplusplus.com/doc/tutorial/polymorphism.html tutorial, i, o ile dobrze zrozumiałem, TO WSZYSTKO JEST BEZ SENSU, i na końcu i tak wychodzi na to samo!

Po co wstawiać funkcje wirtualne do klasy, skoro potem dziedzicząca ją klasa i tak musi ją mieć zadeklarowaną?! nie lepiej od razu zrobić klasę, która bedzie miała w sobie wszystko? w takim razie, skoro długość kodu nie ma znaczenia, to zamiast dziedziczyć nie lepiej ctrl+c ctrl+v i zmienić klasę tak, żeby miała tylko to, co potrzebne?!

W ogóle, nie rozumiem po co bawić się w to całe dziedziczenie - nie lepiej zrobić klasę od początku, z funkcjami, które są potrzebne albo wrzucić wszystko do klasy nadrzędnej? bo to co jest w tym tutorialu wg. mnie tylko wprowadza zamęt. :-|

Wydaje mi sie to być tworzeniem "na siłę" kodu zorientowanego obietkowo, a przecież odwoływanie się do funkcji, która zawiera sie w 10 klasach chyba nie jest bez znaczenia na szybkość działania programu?

Może coś przeoczyłem ale przed chwilą to wszystko naprawdę wydawało mi się głupie.

0

która bedzie miała w sobie wszystko

Tak się nie da zrobić ...
Właśnie polimorfizm pozwala na pewną elastyczność i użycie
kodu który "stworzy" nową klasę zawierającą nowe elementy
bez zbędnej przebudowy kilometrów kodu (który jest przeważnie i tak nie dostępny ,
a jeśli jest to i tak nie warto się z nim mordować ) .

0

no ale np. w przypadku tego tutoriala mogłaby istnieć klasa CPolygon, a w niej funkcje zwracajace pole trojkata, kwadratu... i jeszcze np. zmienna zawierajaca informacje jaka to figura(enum albo liczba) i wtedy mogłabybyć jedna funkcja area() ktora sprawdzałaby jakie ma zwrocić pole.

O i na wiki jest nawet: "Przy możliwościach obecnych komputerów koszt wirtualności jest zaniedbywalny, ale wciąż warto przemyśleć, czy potrzebujemy wirtualności dla wszystkich funkcji." czyli jednak nie jest to bez znaczenia

0

polimorfizm został zrobiony dla wygody programistów ,
nie do optymalizacji kodu lub innych dziwnych rzeczy .
Stosowanie go w prostych przypadkach (na siłę) jest zbędne , ale
w większych programach naprawdę jest pomocny i pozwala
na napisanie kodu łatwiejszego do zrozumienia i konserwacji .
Oczywiście nie ma problemu jak w programie masz 200 linijek to olać wirtual ,
ale jak jest ich 2000 to wygląda to nieco inaczej ,,,..

0

ok thx.

ale przecież, mając bardzo rozbudowaną klasę, mającą wiele zmiennych, to po stworzeniu jej "dziecka"(nie wiem jak to sie inaczej nazywa :P), może sie zdarzyć, że 1/10 z nich jest niepotrzebna w "niższej" klasie, ale co tu zrobić? zajmują niepotrzebnie pamięć, (no bo w konstruktorze są inicjalizowane itp) i mogłoby sie okazać, że czesc z nich moglaby byc tylko w innych "nizszych". albo po prostu (nie rozumiem dlaczego to takie wielkie utrudnienie) zaznaczyć te 500 linijek i skopiować, zmienić nazwe, powywalać co niepotrzebne i dodać swoje metody, zmienne itp. przecież ta operacja jest wykonywana tylko raz, a przy dziedziczeniu trzeba pamiętac wszystko co jest w nadrzednej funkcji, czy przypadkiem cośtam nie było już zadeklarowane i ogólnie wg. mnie to jest "dziwne" ale nie bede sie kłócić bo się nie znam i jeszcze nic nie napisałem ani nie pracuję jako programista :P

generalnie wydaje mi sie ze szybkość programu(optymalizacja) ma większy priorytet niż czytelność kodu...

0

Czlowieku ,, czytaj co do ciebie piszą .

kilometrów kodu (który jest przeważnie i tak nie dostępny

polimorfizm został zrobiony dla wygody programistów

A tak oglnie jeśli istnieje to jest potrzebny , tylko postaraj sie zrozumieć
dlaczego ...
co do optymalizacji całkowicie się z Tobą zgadzam , ale to nie te czasy , można
wszystko napisać w asemblerze ale życie wymaga wydajnego tworzenia aplikacji
i przyznam że obecnie kod wygenerowany przez kompilatory (na podstawie masy kodu źródłowego) jest w 50% (hi ,, jak nie więcej ) nadmiarowy i zawiera rzeczy które są zbędne .....
Ale aby napisać rozbudowaną aplikację funkcjonującą w obecnych systemach
operacyjnych wgryzając się w poszczególne zmienne ( i to nie nasze ale z bibliotek
tworzących program ) to życia nie starczy ...

Acha i nie wystawiaj języka ,,,, [green]
powodzenia ...

0

Kurczę wiesz, pewnie, żę możnaby się bawić w przeklejanie funkcji i tak dalej, ale to i tak przy założeniu, że masz dostęp do treści klasy i tak dalej. chcesz zdziedziczyć po klasie, która jest w jakieś dll'ce? Nie ma większego problemu. Chcesz skopiować jej treść, funckje do swojej klasy? Trochę gorzej,nie?

Poza tym wydajność i wygoda tworzenia aplikacji: napiszesz klasę i jakieś funkcje w niej, skopiujesz to do swojej drugiej klasy. Potem trzeciej i siódmej. Potem znajdziesz błąd w tej klasie, albo kilka błędów, ale żeby porządnie przetestowac, każdą zmiane musisz na nowo siedem razy kopiować do róznych klas. Przy jednym błedzie jest jeszcze do przeżycia, ale przy kilkunastu/dziesięciu zmianach w kodzie klasy, który jest po prostu kopiowany? No ja podziękuję... zdecydowanie wygodniej jest jednak zdziedziczyć, a zmiana sama propaguje się w dół.

0

W ogóle, nie rozumiem po co bawić się w to całe dziedziczenie - nie lepiej zrobić klasę od początku, z funkcjami, które są potrzebne albo wrzucić wszystko do klasy nadrzędnej? bo to co jest w tym tutorialu wg. mnie tylko wprowadza zamęt.

I później masz maszkarę w której jest wszystko i z trudem można się połapać do czego to pierwotnie służyło i gdzie co jest...

0
cr3 napisał(a)

właśnie przeczytałem ten: http://www.cplusplus.com/doc/tutorial/polymorphism.html tutorial, i, o ile dobrze zrozumiałem, TO WSZYSTKO JEST BEZ SENSU, i na końcu i tak wychodzi na to samo!

Po co wstawiać funkcje wirtualne do klasy, skoro potem dziedzicząca ją klasa i tak musi ją mieć zadeklarowaną?!

Nie musi - w przykładzie na tej stronie funkcja "void set_values (int a, int b)" pojawia się automagicznie w klasach dziedziczących, one same nie muszą nawet wiedzieć o jej istnieniu.

nie lepiej od razu zrobić klasę, która bedzie miała w sobie wszystko? w takim razie, skoro długość kodu nie ma znaczenia, to zamiast dziedziczyć nie lepiej ctrl+c ctrl+v i zmienić klasę tak, żeby miała tylko to, co potrzebne?!

Programowanie obiektowe generalnie skraca długość kodu (brak duplikacji kodu/lepsza organizacja) - nie rozumiem na jakiej podstawie wysnułeś przeciwny wniosek.

W ogóle, nie rozumiem po co bawić się w to całe dziedziczenie - nie lepiej zrobić klasę od początku, z funkcjami, które są potrzebne albo wrzucić wszystko do klasy nadrzędnej? bo to co jest w tym tutorialu wg. mnie tylko wprowadza zamęt. :-|

Klasa rodzica ("superklasa") to zebranie cech wspólnych - np. każdy pies ma wzrost i wagę. Szczekanie jest jednak różne w zależności od narodowości - polski pies robi "hau hau", niemiecki "wau wau" a angielski "woof woof" ;)
Dzięki dziedziczeniu kod do wspólnych rzeczy (np. pobranie wzrostu) jest napisany tylko raz - w klasie nadrzędnej, a tylko szczekanie zależy od danego podtypu; unika się dzieki temu duplikacji kodu (nie chodzi tutaj o długość (choć też) ale łatwość modyfikacji - łatwiej zmienić jedno miejsce niż 20).
Spójrz na np. taki kod:

#include <iostream>

class Pies {
  int waga, wzrost;
public:
  Pies(int waga_, int wzrost_) : waga(waga_), wzrost(wzrost_) {}
  int getWaga() { return waga; }
  int getWzrost() { return wzrost; }
  virtual void szczekaj() = 0; //to jest funkcja abstrakcyjna; pies jest bytem abstrakcyjnym
};

class PolskiPies : public Pies {
public:
  PolskiPies(int a, int b) : Pies(a, b) {}
  virtual void szczekaj() { std::cout << "Hau hau" << std::endl; }
};

class AngielskiPies : public Pies {
public:
  AngielskiPies(int a, int b) : Pies(a, b) {}
  virtual void szczekaj() { std::cout << "Woof woof" << std::endl; }
};

int main() {
  Pies *psiak;
  int n;
  std::cin >> n;
  if(n == 1) psiak = new PolskiPies(13, 37);
  else psiak = new AngielskiPies(42, 23);
  std::cout << "pies zaraz sie odezwie" << std::endl;
  psiak->szczekaj();
  delete psiak;
}

Funkcje (akcesory) do pobierania wagi i wzrostu są wspólne, więc zostały zadeklarowane tylko raz.
Funkcja szczekaj jest wirtualna, więc odpowiadająca funkcja zostanie wybrana podczas działania programu - pies 'sam' wie jak ma zaszczekać (implementacja w jego klasie), ty nie musisz się tym zajmować (w przeciwnym przypadku musiałbyś zrobić po prostu if w kodzie dla każdej narodowości).
W przykładzie powyżej funkcja wirtualna zastępuje tylko porównanie - co może być nawet szybsze, ale na pewno nie zwalnia programu.

generalnie wydaje mi sie ze szybkość programu(optymalizacja) ma większy priorytet niż czytelność kodu...

Jest całkowicie odwrotnie, wyłączając może sytuacje typu 'misja na marsa' gdzie masz ściśle określony sprzęt. W zwykłych aplikacjach można się martwić najwyżej złożonością, a i to nie zawsze ma sens. Komputery są naprawdę absurdalnie tanie w stosunku do kosztu pracy potrzebnej przy budowie programu.
Zresztą, jak w przykładzie powyżej, funkcja wirtualna nie zawsze jest wolniejsza.

ale przecież, mając bardzo rozbudowaną klasę, mającą wiele zmiennych, to po stworzeniu jej "dziecka"(nie wiem jak to sie inaczej nazywa ), może sie zdarzyć, że 1/10 z nich jest niepotrzebna w "niższej" klasie, ale co tu zrobić?

Stworzyć nową klasę z rzeczami używanymi w obu i dziedziczyć z niej w dwóch przypadkach. Ew. olać jeśli nie przeszkadzają.

0

Metoda Ctrl+C, Ctrl+V jest największą głupotą na jaką może programista sie zdobyć. Napisałeś klasę - przodka. Po niej dziedziczy 30 klas potomków. Okazało się, że totalnie spieprzyłeś listę do przechowywania współrzędnych wierzchołków. W klasie przodka poprawiasz ten fragment kodu - wszystkie klasy potomne to dziedziczą. Teraz zrób to samo na 30 klasach...

Dziedziczenie wprowadzono dla "napisz - zapomnij". Raz dobrze napisany kod się dziedziczy a nie przekleja.

0

jedna linijka kodu kosztuje średnio 1$ (napisanie, debugowanie, zarządzanie i co jeszcze sobie wymyślisz, sama kwota tylko orientacyjna) - to chyba wyjaśnia, dlaczego ctrl+c, ctrl+v się nie opłaca?

0

Kurczę wiesz, pewnie, żę możnaby się bawić w przeklejanie funkcji i tak dalej...

Mozna, mozna potem poprawiac jednego buga w 30tu klasach zamiast w jednej klasie bazowej ;)

0
EgonOlsen napisał(a)

Kurczę wiesz, pewnie, żę możnaby się bawić w przeklejanie funkcji i tak dalej...

Mozna, mozna potem poprawiac jednego buga w 30tu klasach zamiast w jednej klasie bazowej ;)

Zakladajac, ze sie spamietalo wszystkie 30 kopiowan, a nie tylko 25 ;)

0

co też napisałem parę linijek niżej, żeby nie było, zę nie znam zagrożeń metody copy - paste :P

//tak się wcinam, bo to ode mnie cycata była i nie chce, żeby se kto o mnie jeszcze gorzej pomyslał :P

0

Dodam jeszcze, że istnieją systemy, w których kompilator / runtime potrafi czasem wyeliminować narzut wywołania funkcji wirtualnych - jeśli wie na pewno, która klasa będzie wywołana, a czasem da się to wywnioskować ze statycznej analizy kodu źródłowego / pośredniego. Dzięki temu wirtualki często wykonują się dokładnie tak samo szybko jak normalne wywołania.

Nawet jeśli nie wyeliminuje, to jest to typowo 1, może 2 takty więcej.
Powielenie często wywoływanego kodu w 30 miejscach odbije się na wydajności na pewno mocniej - wystarczy, że się nie zmieści w całości w cache kodu procesora (L1), a wiadomo, że jest on mały (liczony w kB).

Optymalizacją zajmowałbym się na końcu - jak się ma ładną strukturę programu, robi się to o wiele prościej i lepiej.

0

To ja jeszcze dodam, że wywołanie metody wirtualnej to zwykle jedna, dwie /wielodziedziczenie itd./ instrukcje procesora. Dla aktualnych procesorów w optymalnych warunkach ta róznica nie istnieje, call to call, i tak trzeba potoki opróżnić, a że jest ich sporo to mogą niwelować efekty istnienia tej dodatkowej instrukcji, zreszta często jest wykonywana równolegle z poprzednimi. Jak mam być szczery to xnacznie większy narzut daje chociaż minimalnie źle zrobiona pętla. Do tego cstringi na stosie np. - kompilator ma obowiązek stworzyć tablicę na stosie i ją zainicjować, a to boli zdecydowanie bardziej niż polimorfizm. Kolejna sprawa - pakowanie danych w strukturach - wyrównanie pól, tak samo wyrównanie stosu czy danych ogólnie, to wszystko się ustawia. Wyrównanie ma straszny wpływ na wydajność, ze względu na cache. Znasz wszystkie cechy platformy, na którą piszesz? Dam głowę, że nie wiesz o opóźnieniach generowanych przez użycie shortów... ale z drugiej strony shorty będą szybsze od intów przy większych tablicach - zdecydowanie mniej wymiany cache-RAM. Nawet takie signed\unsigned ma wpływ... Procesory wykonują jeżeli tylko mogą po kilka instrukcji jednocześnie - wpasuj sobie tutaj narzut późnego wiązania. W skrajnym wypadku jak nie robisz nic więcej jak tylko wołasz w pętli metody stracisz może kilka procent, przy bardziej skomplikowanych operacjach narzut jset w promilach bądź nie istnieje. Ważniejszy jest algorytm. Tak, faktyczny czas wykonywania zależy od złożoności. Denerwują mnie 'programiści C++' liczący każdy cykl procka - to tylko dowód nikłego pojęcia o rzeczy. Co do nadmiarowości kodu - nie zgodzę się, przy nadużywaniu OOP jest wiele 'zbędnego' kodu, ale temu jest winien przede wszystkim programista. Hm, tak, zabawki Borlanda i biblioteka VCL - przykład jak nie używać OOP.
Po pierwsze - OOP poprawia znacząco organizację kodu, zapewnia możilwość jego wielokrotnego wykorzystania przy odpowiednim zaprojektowaniu, znacząco kod skraca i upraszcza.

Wydaje mi sie to być tworzeniem "na siłę" kodu zorientowanego obietkowo, a przecież odwoływanie się do funkcji, która zawiera sie w 10 klasach chyba nie jest bez znaczenia na szybkość działania programu?

Wywołanie metody z którejś z wyższych klas w drzewie to zwykle zwykłe wywołanie funkcji + ew. korekcja thisa - to tak jakbyś do globalnej funkcji przekazał strukturę przez wskaźnik jawnie. Przy dziedziczeniu wirtualnym, bardziej złożonej hierarchii klas dochodzi czasem wspomniana korekcja ale to znów tak jak w przypadku metod wirtualnych niezauważalny narzut. Takie kopiowanie metod jak wspomniałeś pomijając straszne koszty konserwacji i ryzyko błędów mają jeszcze jedną poważną wadę - znacząco powiększają program, tak kod źródłowy jak i maszynowy. Obie cechy są niekorzystne.
Funkcje wirtualne mają za zadanie zapewnić jednakowe działanie metody dla każdego poziomu hierarchii klas - takie, jak zdefiniowała najniższa zmieniająca działanie klasa w drzewie. Co to daje za wyjątkiem polimorfizmu na klasie bazowej? Ano to, że metody z klasy bazowej mogą używać metod wirtualnych, np. akcesorów - klasa bazowa implementuje całą mechanikę niezależną, wejśćie\wyjście definiują klasy pochodne. Cały vic polega na tym, że klasa bazowa może robić ciekawe rzeczy nie przejmując się tym czy czyta\zapisuje dane w pamięci, pliku czy może przez sockety. Jaki jest efekt? Powiedzmy, że piszesz klasę protokołu komunikacyjnego, pobiera i wysyła pojedyncze bajty... ale sposób komunijacji może być skrajnie róźny - dzięki metodom wirtualnym masz całą mechnikę napisaną raz, obojętne czy używasz portu równoległego, szeregowego, głośniczka systemowego czy interface'u do ekologicznych znaków dymnych - implementujesz tylko dwie metody + konstruktor dla każdego nowego sposobu komunikacji. Jak jakiś buc rozgryzie nasze cudowne szyfrowanie xor'em to powodzenia w dodawaniu negocjacji klucza i szyfrowania asymetrycznego w Bóg wie ilu klasach, tak żeby wszystko chciało działać. Powiedz klientowi, że w zamian za kolejne 6 m-cy wymagania programu będą oscylować w okolicach Pentium 90MHz zamiast 100MHz, powinien się ucieszyć ;-P
Dziedziczenie i komponowanie obiektów wydatnie skraca czas tworzenia oprogramowania, podnosi jego niezawodność itd.
Co do wirtualności wszystkich funkcji - wirtualne powinny być tylko te, których zmiana zachowania jest sensowna, te które określają zachowanie specjalizacji klasy.
A propos 'niepotrzebnych' pól klas - dziedziczysz także metody i całą mechanikę, jeżeli w klasie, z której dziedziczysz te pola były używane to i klasa pochodna ich będzie używać. Zresztą - bardzo duża klasa to błąd projektowy, każda klasa powinna wykonywać tylko jedno ściśle określone zadanie.
Wiesz, to zakrawa na hipokryzję - przejmujesz się kilkoma polami, które może nie będą potrzebne a chcesz kopiować całą impelemntację klas nadrzędnych. Płaczesz nad kilkoma 'marnowanymi' bajtami marnując całe kilobajty.

generalnie wydaje mi sie ze szybkość programu(optymalizacja) ma większy priorytet niż czytelność kodu...

Dziedziczenie jest szybsze niż kopiowanie, to raz - ta sama metoda klasy bazowej jest wołana dla klasy pochodnej - kłania się cache procesora. Co do czytelności, 'napisz i zapomnij' to niezbyt dobry pomysł jeżeli masz zamiar jeszcze do kodu zaglądać - piszesz w języku wysokiego poziomu do diabła, część kompilatorów wspiera nawet generowanie kodu podczas linkowania, napisany przez Ciebie kod nie ma bezpośredniego przełożenia na maszynowy. Ty implementujesz algorytmy + IO i trochę niskiej mechaniki, kompilator robi resztę. Mały przykład, nieco 'funkcyjny':

#include <iostream>
#include <functional>
using namespace std;

const unsigned uLipotes = 0x44;
const unsigned uVexillifer = 01;

int main() {
	cout << &uLipotes << " " << &uVexillifer << endl;
	cout << bind1st(plus<unsigned>(), uLipotes) (uVexillifer) << endl;
	return 0;
}

Co to robi? Wypisuje adresy stałych /żeby wymusić ich obecność/ i za pomocą obiektów funkcyjnych oblicza ich sumę... jak powinno wyglądać najbardziej interesujące nas wyrażenie? Tworzony jest obiekt klasy plus, po konkretyzacji szablonu, oferuje on operator(), następnie idzie do konstruktora bind1st - kolejny obiekt funkcyjny, posiada jednoargumentowy operator() i związane w sobie argumenty z konstruktora, które w operatorze () łączy i wywołuje. W końcu jawne wywołanie metody bind1st::operator()(unsigned), które z kolei robi niejawne wywołanie metody plus<unsigned>::operator()(unsigned, unsigned). I co? Powinno gdyby kompilator bezpośrednio to na binarkę przekładał mieć narzut większy niż Visual Basic ale, z debuggera, standardowe ustawienia przy kompilacji:

	cout << bind1st(plus<unsigned>(), uLipotes) (uVexillifer) << endl;
004016EE  push        45h  
004016F0  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (401810h) 

Czyli? Ano całość zostałą przekształcona i obliczona podczas kompilacji. Wnioski? Ty piszesz, kompilator robi po swojemu. Przykład może niezbyt sensowny ale ilustruje dobrze jakie różnice powstają w kodzie.
Mały apel - ludzie, nie myślcie niskopoziomowo tam, gdzie nie jest to wymagane. Nie tylko utrudnia to tworzenie kodu ale i potrafi się negatywnie na jego jakości odbić. O wydajności myśli się kiedy ma się już rozwiązanie problemu, i tylko wtedy gdy aktualna jest niewystarczająca. W pierwszej kolejności optymalizacja powinna polegać na zmianie algorytmu, mniejsza złożoność jest ważniejsza. Mówiąc krótko - optymalizować z głową, tylko gdy zapewni to sensowne korzyści.

Hm, tak, miałem pracować ;-P

0

PO czym poznać dobrego programiste? Nie ma zatartych przycisków C, V i CTRL ;)

0

Wtrącę trzy grosze. Obecnie moc obliczeniowa i wielkość pamięci są bardzo tanie. Minęły czasy gdzie robiło się masakryczne sztuczki optymalizacyjne i walczyło o każdy bajt ramu. przy obecnej komplikacji systemów często nad szybkość stawia się stabilność bo co za różnica czy user będzie miał generowany raport z bazy w 0.1123 s czy 0.3255. Różnica 3x a i tak nikt nie odczuje.

0

jednak przesada w drugą stronę też dobra nie jest - dobrym przykładem jest Firefox i to, ile dało się zoptymalizować... Przynajmniej pod linuxem różnica szybkości jest kilkukrotna (pod windowsem nie próbowałem, ale jeden kolega trochę narzekał)

0

Nie, no wiadomo. Trzeba pamiętać, że pomiędzy szybkością a stabilnością musi się jeszcze znaleźć zdrowy rozsądek

0

Oj, Firefox to akurat antyprzykład tomkiewiczu podałeś ;)
Patrząc na FF można śmiało powiedzieć, że na optymalizację można lać ciepłym moczem bo
1.1 nawet wolna kobyła się świetnie przyjmie, jeśli posiada funkcjonalność.
1.2 nawet totalnie zwaloną kobyłę można zoptymalizować po x latach (i to kilkukrotnie), więc...
1.3 ignorując wydajność na początku nic nie ryzykujesz - a stawiając na optymalizację możesz wtopić na polach, których nadrobić się nie da - czytelności, elastyczności i strukturze kodu.

Szybki chaotyczny kod można przepisać jedynie w całości, dobry wolny kod można profilować w tych miejscach, gdzie trzeba.

Właśnie... gdzie trzeba - deus świetnie i wyczerpująco wykazał, że źródło sobie, a kompilator sobie. A jeszcze nowsze języki nie są natywne (wszystkie Javy, NETy, Perle i Pythony), a to znaczy, że masz podwójnie czeski film - kompilacja do bytecode'u (albo interpretacja) zrobi czystkę nr 1. Wirtualna maszyna zrobi czystkę nr 2. I za ch... nie poznasz tego, co napisałeś.

Zabawy w jasnowidza i twierdzenia na czuja (jeszcze przed napisaniem i testami wydajności), że "to będzie wolne", prowadzą najczęściej do marnowania czasu i ludzi na optymalizowanie kodu, który sumarycznie przyniesie promilowy zysk - a później się okazuje po profilowaniu, że optymalizować i tak trzeba - ale dla odmiany, w realnych wąskich gardłach, a nie w urojonych.

Generalnie, w desktopowych zastosowaniach to bym 2 spostrzeżenia dodał:
2.1 program działający 1s ("zwis") zostanie gorzej odebrany przez userów, niż program działający 5s, ale ze ślicznym paskiem postępu, który miga, tańczy i śpiewa (okropne... ale prawdziwe)
2.2 duży projekt trwa - pół roku, rok, a gry komputerowe to i kilka lat. To co programiście muli, na sprzęcie klienta za rok będzie fruwać. Zaczynając duży mocożerny program można mu stawiać wymagania na granicy dzisiaj dostępnych - przy wypuszczeniu będzie średniakiem

No i obecnie najbardziej wymagająca dziedzina: obliczenia rozproszone albo aplikacje dla serwerów / serwisy www - żal mówić, ale koszty dokupienia nowego klastra 50 maszyn jest śmieszny w porównaniu z kosztami optymalizowania przez pół roku czegoś tam, gdzieś tam (zamrożenie projektu, który mógłby zarabiać). A i optymalizacje w tych dziedzinach to nie żadne liczenie cykli, ale projekt architektury i działania wysokopoziomowe (buforowania w każdej postaci, równoważenie obciążenia, wszelkie proxy... itd itp).

Generalnie to nie wiem, czy na PC jeszcze gdziekolwiek realnie istotne jest liczenie cykli i instrukcji, biorąc pod uwagę, że większość technik przyspieszania programów to działania na dużo wyższym poziomie abstrakcji (często wyższym nawet niż HLL, którego użyto do implementacji)

0

mój post był może za bardzo skrótem myślowym - chodziło mi o to, że wiele osób, jak jeszcze fx2 zabierał udziały jedynce, twierdziły uparcie, że firefox2 musi być powolny - modułowa budowa, oparcie o javascript, stuktura kodu itp. A jednak się dało.

A z tym co napisałeś też się zgadzam - to akurat inny aspekt tematu. No... prawie się zgadzam ;)

Jeżeli pewnych optymalizacji, nie wykona się na etapie projektowania, później będzie to trudno zmienić - na przykład struktura bazy danych - owszem, można się zasłonić obiektową obudową, ale może też być taka sytuacja, że klient zgodzi się na lekkie zubożenie funkcjonalności w zamian za znaczący przyrost wydajności. Jeżeli by taką modyfikacje zacząć wprowadzać po testach wydajnościowych (kiedy projekt działa lub prawie działa), koszty mogą się okazać dość wysokie.

Z Twoją tezą o paskach postępu się w żaden sposób nie zgadzam - responsywność programu jest akurat bardzo ważną rzeczą - pomijając brak zdenerwowania użytkownika (jak widzi, że program nie wisi), nie musi się on zastanawiać, czy już ma restartować komputer, czy poczekać jeszcze z minutę

0

@tomkiewicz - czyli potwierdziles teze Ranidesa.. uzytkownik woli program 5deltaT ale prezentujacy 'uwaga, teraz pracuję' niz program 1deltaT ktory nie jest 'responsywny' :)

0

no tak, użytkownik woli. Ale Ranides tak to napisał, że odniosłem wrażenie, że według niego lepiej, żeby program działał trochę (paski postępu zazwyczaj nie narzucają pięciokrotnego podniesienia czasu wykonania ;) ) szybciej kosztem totalnej zwiechy na czas działania.

aplikacja dla użytkownika to nie tylko algorytmy, a paski postępu po coś ktoś wymyślił :>

a teza dotyczyła pasków postępu i okropności :)

0

nu nu nu, nie o narzut paska mi chodziło.
Chodzi mi o ból w tym sensie, że ProgressBara to każdy debil umie wstawić, a przyspieszyć aplikację o 80% to już tylko profesjonalista i to pewnie siwiejąc i siedząc po nocach. A użytkownicy lepiej odbiorą efekt "pracy" debila ;)

To nie jest ból obiektywny, tekst w nawiasie to jedynie subiektywne odczucie było moje, jako ludzia od kodu ;) Hm... dobrych ludzi od UI szanuję, ale do tej pory spotkałem dwóch, a reszta ludzi od 'ProgessBarów'... [cut]

A weź tomkiewiczu, ja Ci się tłumaczę ze swoich odczuć, kiedy z tezą ogólną obaj się zgadzamy, przestań ;p

0

A propos progressbarów, to mnie denerwuje, że żaden ze znanych mi szanujących się systemów baz danych nie potrafi wyświetlać progressbara jak wykonuje okropnie skomplikowane, długie zapytanie. I nawet nie wiem, czy mam czekać jeszcze 5 minut, czy może zrezygnować. Ale jak zrezygnuję, to zawsze może być tak, że przerwałem mu akurat, gdy już prawie wszystko miał policzone.

0

Chodzi mi o ból w tym sensie, że ProgressBara to każdy debil umie wstawić, a przyspieszyć aplikację o 80% to już tylko profesjonalista i to pewnie siwiejąc i siedząc po nocach. A użytkownicy lepiej odbiorą efekt "pracy" debila ;)

Skoro każdy debil umie wstawić, to dlaczego Pan Super Programista Zaawansowanej aplikacji tego progressbara nie wstawia ? :P
Tak nawiasem mówiąc wcale niełatwo napisać ładnie wyglądającą aplikacje, więc mam szacunek do ludzi zajmującymi się interfejsami graficznymi.

0

Nie mówimy o ładnym gradientowym pasku postępu wykorzystującym DX 10 tylko o jakimkolwiek pasku postępu... A nie wstawia bo stracił już tyle czasu na optymalizację, że o ja pie...

0

Na brzydkiego progressbara to się użytkownicy też raczej nie złapią.

0

W bazach danych chciałbym mieć jakikolwiek progressbar.
Może być 2D, 3D, z melodyjką lub bez, a nawet wystarczy w zupełności tekstowy zrobiony z kropek lub myślników. Byle bym wiedział mniej więcej, czy będę czekał jeszcze kilka sekund czy 5 godzin.

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