Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Krótka opowieść programistyczna o Swingu-Kłamczuszku

Jak często spotykacie programistów, którzy na pytanie: „Jakie technologie lubisz najbardziej?” odpowiedzą: „Im starsze, tym lepsze, koleś!”? Pewnie nieczęsto. Starożytne budowle do dziś potrafią zachwycać inżynierów swoją trwałością i przemyślaną konstrukcją. Tymczasem „zaledwie” 10 lat w informatyce jest okresem, w którym futurystyczne wizje odchodzą do lamusa, a pomysły relatywnie świeżę uznawane są za przestarzałe.

Nie zawsze jednak możemy pracować w tym w czym byśmy chcieli, w szczególności jeśli brak doświadczenia nie pozwala nam na szybką ocenę przyszłej pracy (na samym dole się do tej myśli odnoszę – przeczytaj nim skomentujesz!). W efekcie przychodzi nam pracować w projekcie, który jeszcze długie lata będzie rozwijany, mimo że pod spodem mamy mały „skansen”.

Technologią, którą przyszło mi „pokochać” jest od jakiegoś czasu Swing, czyli biblioteka tworzenia GUI, z którą Java żyje jakieś 20 ostatnich lat. Inaczej mówiąc, Swing powstał w czasach w czasach nie mniej ciekawych niż obecne (choć chyba bardziej pionierskich). Z jednej strony był to okres premier pierwszych Windowsów z serii 3.x, pierwszej stabilnej wersji języka Java oraz początków WWW. Z drugiej strony był to czas prężnego rozwoju inżynierii oprogramowania, a w szczególności dzięki Bandzie Czterech spopularyzowany został wtedy termin Wzorzec projektowy. Wiele z pomysłów, które dziś są czymś oczywistym (w znaczeniu: „oczywiście, że są złe” lub „oczywiście, że są dobre”), wtedy dopiero przebijały się do mainstreamu.

M-WTF-C

Jeśli ktoś miał styczność z rozwojem interfejsów graficznych, prawdopodobnie korzystał z jednej z implementacji wzorca MVC. Architektci Swinga również o nim słyszeli. W artykule opisującym proces projektowy możemy jednak przeczytać:
The first Swing prototype followed a traditional MVC (…).
We quickly discovered that this split didn't work well in practical terms because the view and controller parts of a component required a tight coupling (…). So we collapsed these two entities into a single UI (user-interface) object…
Nie sposób sprawiedliwie ocenić tamtejsze decyzje (trzeba np. pamiętać, że Swing powstawał wiele lat przed wprowadzenie typów generycznych do Javy). Widać jednak, że technologia ta nie przystaje już do obecnych nam czasów, w szczególności, gdy powstaje coś większego niż hello-world-calkulator. Nie tylko coraz bardziej wonieje kod z pomieszanymi rolami, ale choćby samo wykańczanie rolki myszki od przewijania zbyt dużych klas powinno zapalać „żółte światło”.

:-|

?V?

Pozostaje traktować to jako swoisty znak czasów. Mam więc Swinga z jego szczególną wersją MVC. Zaczynamy projektować swój interfejs w zgodzie z jego architekturą. Nasza aplikacja posiada wyraźny podział na model i widok-kontroler.

BUM! Budzi mnie wgniatająca się w policzek klawiatura. Orientujecie się, że to był tylko sen. Z ekranu spogląda na mnie jakaś programistyczna chimera :-( .

Z jakiegoś powodu w Swingu są komponentu, które z całego MVC oferują tylko środkowe V (trochę jak środkowy palec prawej dłoni, hmmm).

Polubiłeś M-VC? No to szkoda :->
Przykład dla zainteresowanych: JLabel (zresztą chyba jeden z częściej wykorzystywanych komponentów). Na pierwszy rzut oka obiekt niezmienny, czyli raz utworzony, pozostaje taki na zawsze. Ale czy na pewno? Nic go nie chroni przed skutkami ubocznymi, np. możemy zrobić tak: // etykieta udająca, że jest tylko widokiem JLabel justSimpleLabel = new JLabel("Nie robię nic ciekawego"); justSimpleLabel.setText("Okej, jednak robie..."); Zatem nie jest to zwykły widok. A mimo to nie ma modelu, którym można by manipulować…

:-/

M vs. V

MVC jeszcze raz. Idea jest prosta: trzy luźno powiązane elementy, mające w jak najlepszy sposób spełniać swoje role. A Swing? Powinno być podobnie: dwa niezależne elementy, (mimo ograniczeń) mające w jak najlepszy sposób spełniać swoje role. W szczególności oznacza to, że widok-kontroler najlepiej odzwierciedla wizualną stronę i relację z modelem, sam model zaś najlepiej nadaje się zarządzania danymi. Przy okazji w Swingu dla „uproszczenia” widok-kontroler oferuje również bezpośredni dostęp do zawartości modelu. No to sprawdźmy to…

Jednym z częściej używanych komponentów jest pole tekstowe. Tutaj JTextField. Jest też model, tu nazwany Document. Oferuje on mniej więcej to, czego można oczekiwać (a może nawet trochę więcej). Sprawdźmy więc jak to działa najbardziej trywialnym przykładzie, w którym manipulujemy zawartością pola tekstowego: // metody widoku, czyli zbędny dodatek // pobranie tekstu z widoku String content = myTextField.getText(); // przekazanie tekstu do widoku String newContent = "nowa zawartość"; myTextField.setText(newContent); // vs. // metody modelu, czyli najważniejszy dla nas fragment // pobranie tekstu z modelu int length = document.getLength(); String contentTheHardWay; try { contentTheHardWay = document.getText(0, length); } catch (BadLocationException badLocationException) { new OhWhyCheckedException("I'm sorry... So sorry...", badLocationException); } // przekazanie tekstu do modelu String newContentTheHardWay = "nowa zawartość"; try { document.remove(0, document.getLength()); document.insertString(0, newContentTheHardWay, null); } catch (BadLocationException badLocationException) { new OhWhyCheckedException("I'm sorry... So sorry...", badLocationException); } Jak widać, w Swingu model zawsze ma priorytet jeśli chodzi o wygodę, klarowność, bezpieczeństwo. W przykładzie z JTextField widok nie pozwala określić zbyt wielu parametrów wejściowych… Co jest jak najbardziej ZŁE. Co gorsza, jeśli w metodzie widoku coś pójdzie nie tak, jak wtedy żyć? Tylko używając modelu, możemy uprościć sobie pracę jawnie przekazując parametry (i to, że będziemy to ZAWSZE robić tak samo, byłoby tylko niegrzeczną wymówką od nierobienia tego w ten sposób!). Eh, spójrzcie jeszcze na te FATALNE nazwy metod w widoku! Najważniejszy jest jednak kontrolowany wyjątek. Dzięki niemu żaden śmierdzący i leniwy programista nie zignoruje krytycznych wyjątków naszego pola tekstowego. WIN WIN WIN…

:-[

M vs. V jeszcze raz

Idea jest prosta: trzy luźno powiązane elementy… I ten nieszczęsny JTextField.

JTextField ma krewniaka. JFormattedTextField. Idea jest świetna: wystarczy ustawić odpowiedni format akceptowalnej zawartości i reszta robi się sama. Tylko liczby? Tylko kwoty pieniężne? Tylko konta bankowe? Proste, a nawet bardzo proste! Przestałem tego używać po zmarnowaniu całego dnia na szukaniu błędu…

Zaczęło się od tego, że dostałem prośbę, by przy wprowadzaniu liczb kropka '.' zamieniana była na przecinek ','. Prosta prośba, którą jednak można zrealizować na wiele różnych sposobów. Ja wziąłem Document i dopiąłem do niego DocumentFilter (mimo swej nazwy można nim zarówno zubażać zbiory wprowadzanych znaków, jak i wzbogacać). Na zwykłym polu tekstowym mój „filtr” po wprowadzeniu kropki zmieniał ją na przecinek. Niestety w przypadku JFormattedTextField efektu nie było żadnego…

Prosta idea MVC mówiąca o luźno powiązanych elementach coś oznacza. Oznacza, że komponenty mają na siebie tylko taki wpływ, jaki muszą. Co to jednak znaczy „muszą”? JFormattedTextField w hierarchii Swinga jest widokiem-kontrolerem, a dokument modelem. Ale czy na pewno? No cóż… JFormattedTextField jest raczej widoko-kontrolero-modelem, który w swej schizofrenii dalej pozwala na wtłoczenie Documentu. Dodanie filtra do tego Documentu jest jednak bezcelowe, gdyż za chwilę nasz swingowy paczworek podmieni go na swój własny… Ręka do góry ilu z was potrafiłoby się tego domyślić w rozsądnym czasie?

:-(

Jestę komponentę… JComponentę!!!

Porzućmy wreszcie to umęczone MVC. Lubię idee czystego kodu. Czemu więc nie przyjrzeć się pod ich kątem Swingowi?

Lubię np. przewidywalność kodu. Weźmy znane i lubiane (mhm, ^_^ ) figury. Figury dają się narysować. Kwadrat też jest figurą! I jak wezmę kwadrat, to próba narysowania go też skończy się rysunkiem! Nie melodią, nie dostawcą pizzy czekającym na gotówkę, ale rysunkiem! W Swingu jest tak saaaa… W Swingu bywa różnie.

Co będzie naszym swingowym odpowiednikiem figury? Będzie nim JComponent. JLabel to JComponent.

… i JCheckBox to też JComponent.

… i JButton to też JComponent.

… i JTable to też JComponent.

I generalnie rzecz biorąc jest spoko. Jak chcę żeby mi mój komponent się przerysował, to nie interesuje mnie jaką konkretnie jest implementacją: List<JComponent> components = createList(); components.add(new JTable()); components.add(new JButton()); // itd... foreach (JComponent component : components { component.repaint(); } Ma sens? Ma.

To teraz załóżmy, że programuję arkusz kalkulacyjny w Swingu. Najważniejszą funkcją arkuszy kalkulacyjnych jest oczywiście kolorowanie komórek. W Swingu możemy sobie wziąć tabelkę i pokazać jej w jaki sposób należy renderować poszczególne komórki, żeby miały nasze ulubione kolory. Służy do tego TableCellRenderer, który dla programisty jest prostym interfejsem. Całość wygląda dość fajnie – ktoś użył odpowiedniego rozwiązania w odpowiednim miejscu (konkretnie wzorca Strategia).

Co jeśli wolimy jednak by Swing rysował komórki po swojemu? JTable zacznie z domyślnie ustawionym DefaultTableCellRenderer. Tylko czym on właściwie jest? Patrzymy na hierarchię dziedziczenia i… JComponent??? A pamiętacie jak pisałem, że lubię przewidywalność kodu? No to: void invalidate() // Overridden for performance reasons. boolean isOpaque() // Overridden for performance reasons. void repaint() //Overridden for performance reasons. // itd... Komponent, który ma robić za konkretną „strategię”? A potem komuś i tak nie podobają się jego metody i wycina ich logikę? To po co w ogóle dziedziczyć po JComponent? Gdzie jest sens tego?

Jestę JComponentę… i niczym więcej?

Wiemy już czym są nasze komponenty. Dużo gorzej się robi, gdy się dowiadujemy, czym one nie są… Ale od początku. Mamy sobie w okienku nagłówek i kilka komponentów, w których można coś poprzestawiać. Chcemy też, żeby w wersji pirackiej za karę nie dało klikać się w te komponenty: JLabel headerLabel = new JLabel("Nagłówek"); JTable table = new JTable(); JButton button = new JButton(); JCheckBox checkBox = new JCheckBox(); void disableIfIllegal() { if (!isLegal()) { table.setEnabled(false); button.setEnabled(false); checkBoxsetEnabled(false); } } „Małpia” robota, co nie? Widać, że wszystkie nasze komponenty mają metodę setEnabled() . Wszyscy znamy podstawową zasadę DRY oraz wierzymy w umiejętności twórców Javy. Wystarczy zatem sprawdzić, który z interfejsów implementowanych przez wszystkie nasze komponenty odpowiada za tę metodę i dzięki polimorfizmowi postanawiamy zrobić coś na kształt: void disableIfIllegal() { if (!isLegal()) { foreach (SomethingLikeEnableable enableable : getComponents()) { enableable.setEnabled(false); } } Do pełni szczęścia brakuje nam jeszcze tylko nazwy interfejsu. Sprawdzamy więc… I co? Okazuje się, że nie ma żadnego Enableable. Każde setEnabled jest po prostu jakąś metodą i tylko przypadkiem nazywają się one tak samo. A nasze sprytne foreach? Może gdyby w Javie było duck typing. A jeśli komuś urodziło się sto komponentów w okienku? component1.setEnabled(false); component2.setEnabled(false); component3.setEnabled(false); // ... ^_^ component100.setEnabled(false);

:'-(

A kiedy siła argumentu nie starcza, pojawia się argument siły…

W chwilach słabości zdarza mi się czasem wpadać na głupie pomysły. Jest np. 15:00 i brakuje mi poczucia konstruktywnie spędzonego czasu w pracy, ponieważ od 9:00 jedyne co udało mi się napisać, to 15 prób rozwiązania problemu, którego natury nie rozumiem ja, ani żaden z kolegów, ani żaden z użytkowników StackOverflow, ani żadnego innego pomocnego forum… Czasem zaczynam się w takich sytuacjach zastanawiać, czy może po prostu błąd nie leży gdzieś po stronie używanego narzędzia.

I kiedy kiedyś nie mogłem zrozumieć natury błędu związanego z używaniem przeze mnie JTable, w akcie desperacji, po prostu postanowiłem sprawdzić bebechy JTable (wchodzicie tam na własne ryzyko). Jest tu według mnie kilka problemów.

Po pierwsze jak duży musi być pojedynczy plik z kodem, by był za duży? Dla mnie za duży jest wtedy, kiedy źle się go czyta. Słusznie? Nie wiem. To może zobaczmy co inni o tym sądzą, np. tu.

Po drugie, nawet gdybyśmy się umówili, że sam rozmiar pliku nie jest żadnym wyznacznikiem, tu według mnie mamy przykład klasy, w której dzieje się po prostu zbyt wiele. Pomijając wspominaną wcześniej przypadłość Swinga polegającą na tym, że mimo dostępu do modelu, widok-kontroler i tak „dubluje” jego metody, mamy tu zarówno wysokopoziomowe operacje związane np. z dostosowaniem powierzchowności, jak i dość niskopoziomową manipulację na poziomie wyliczaniu liczby pikseli.

Skutek dla mnie jest taki, że rozwiązania mojego problemu do dziś nie znam, gdyż otwarcie kodu JTable było dla mnie jak uderzenie obuchem w głowę. Uznałem, że e nie mam tam czego szukać i pozostało mi żyć z poczuciem, że pokonano mnie argumentem siły…

;'-( ' '

(A gdyby kogoś to interesowało, mój problem polega na tym, że gdy chciałem by kolejne komórki tej samej kolumny tabeli otrzymywały losowe kolory, to zarówno korzystając z domyślnie generowanego renderera komórek, jak i tworząc własny, który rozszerzał DefaultTableCellRenderer i tak zawsze wszystkie dostawały kolor ten sam – pierwszy spośród wszystkich wylosowanych. Magia polega na tym, że jeśli renderer został stworzony przy użyciu metody JTable#getDefaultRenderer(Class<?> columnClass) wszystko zaczynało magicznie działać tak, jak tego chciałem.)

Wciąż rozwijana biblioteka

Pomimo wszystkich cool story, z którymi się tutaj z wami podzieliłem mógłbym ten wpis zakończyć jakimś pozytywnym akcentem, np. opowieścią, że z nadzieją patrzę w przyszłość wiedząc i widząc, że Swing jest wciąż kochany, rozwijany i powszechnie używany. Wolę jednak po prostu sprawiedliwie tę bibliotekę ocenić.

Miłość. Z „miłością” do Swinga bywa różnie. Pod wieloma względami podoba mi się on bardziej niż np. Androidowe API (mimo, że jest to znacznie nowocześniejsze narzędzie, nie miałem poczucia, by twórcy podstawowych komponentów androidowych słyszeli kiedykolwiek o jakiejkolwiek wersji MVC, czystym kodzie i podobnych rzeczach). Nie być najgorszym w swojej klasie, to jednak zdecydowanie za mało na jakieś cieplejsze uczucia.

Rozwój. Rozwój Swinga, owszem, do niedawna był jeszcze widoczny (ostatnia jakaś istotniejsza zmiana to chyba czasy Javy 7). Sęk w tym, że mamy do czynienia z czasem przeszłym. Ponadto czasem wręcz chciałoby się krzyknąć CZEMU TAK PÓŹNO?!. Prosty przykład to „generyki”. Ogólnie w Javie zawitały już w wersji 5. A w Swingu? Ktoś się obudził i nagle stwierdził, że świetnym pomysłem byłoby również w tej bibliotece skorzystać z takich dobrodziejstw. Stało się tak dwa wydania później… w bardzo ograniczonej formie.

Innym przykładem niech będą propozycje nowości z czasów Javy 6. Programiści Swinga wpadli na kilka mniej-lub-bardziej fajnych pomysłów i wrzucili je do osobnej biblioteki SwingX. Miały one stać się standardem w następnej wersji Javy. Udało się? Niestety tylko część propozycji została przyjęta. Reszta żyje dalej w SwingX, który obecnie nie posiada nawet strony domowej…

Powszechne użycie? Nie muszę chyba pisać, że w kontekście powyższych wniosków nie sposób traktować powszechnego użytku tej biblioteki jako coś pozytywnego, prawda?

PS

Mimo takiej, a nie innej mojej opinii o Swingu, traktuję doświadczenie nabyte w pracy z tą biblioteką jako coś bardzo cennego. Uważam, że jeśli nie dostajemy narzędzi, które lubimy, warto spróbować polubić, te które dostaliśmy. Zmienić można podejście lub pracę, bo narzędzia zmieniają się najwolniej. Niech to będzie moja pozytywna myśl na koniec tego wpisu :-) . 

programowanie

Komentarze

0 nowych
awangardowy   7 #1 27.03.2015 23:45

swing umiera, javafx jest trendy

Frankfurterium   10 #2 27.03.2015 23:56

Swing... Trochę się nakląłem na wątki (masa asynchronicznosci, duużo SwingWorkerów, problemy z repaintowaniem komponentów poza EDT), osobne implementacje AWT na różne platformy albo częste "TODO: this is ugly" pozostawione w kilkuletnim kodzie komponentów. A potem natrafiłem na graficzne frameworki z ładniejszym API ale nawet nie w połowie tak gotowe do pracy jak Swing...

awangardowy   7 #3 28.03.2015 00:04

ja chcialem sobie poćwiczyć i nauczyć się jakiegoś front endu dla javy, wszystkie najbardziej klasyczne rozwiazania mowia o "swing", ale w sumie - po wywiadzie z kolegami"w tym fachu" - wybrabym teraz wlasnie javafx.
tutaj prosty hello world:
https://www.jetbrains.com/idea/help/developing-a-javafx-hello-world-application-...

zastanawiam się w sumie czy to nie używa jakiś bibliotek systemowych typu DLL, bo wygląd tego czegoś jest inny od "klasycznej" javy w swingu napisanej ;)


swoją drogą:
https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/fx_swing.htm#J...

inegracja javafx z swing... moze warto jednak wrocic do swing, tak sobie mysle teraz

Autor edytował komentarz.
MaXDemage   18 #4 28.03.2015 08:34

Im starsze tym lepsze koleś? COBOL FTW! ;>

Frankfurterium   10 #5 28.03.2015 10:00

@awangardowy: Swing ma mechanizm Look And Feel, gdzie w paru linijkach można zmienić całościowy styl aplikacji. W FX zwie się to chyba AgentStylesheet.
Tak czy siak, teraz nie pchałbym się ani w Swinga, ani w FX-a. Mimo lansowania przez Oracle'a tego drugiego desktop to dla Javy stracony rynek. Firmy utrzymują tylko stary kod, a wszystko nowe przenoszą do weba. Web też oferuje parę frameworków, gdzie GUI tworzy się w swingowym stylu, ale i one są ostatnio wypierane przez różne JavaScripty (a JavaFX przez przeglądarkę... lepiej unikać).

  #6 28.03.2015 10:09

Cholerni puryści... przychodzą tacy młodzi ze studiów, czy innych szkół i wszędzie tylko wzorce projektowe by tylko implementować chcieli, wszędzie tylko "czysty kod" widzieć, albo optymalizować złożoność algorytmu sortowania dziesięciu elementów, no bo przecież profesor uczył i mądry pan w książce napisał.

Rzeczywistość jest jaka jest, jedyny czysty kod, to ten, który nie został napisany. Połączenie widoku i kontrolera było jak najbardziej w porządku. Główną bolączką Swinga jest sędziwy wiek i zaszłości z czasów jednowątkowych. Większość frameworków frontendowych ewoluuje od stricte purystycznych architektur w stronę "brudniejszych", ale znacznie efektywniejszych w użyciu systemów.

Airborn   8 #7 28.03.2015 11:20

W paru linijkach zmienić LAF? Może w jakichś drobnych rzeczach to tak, ja skończyłem z XMLem na 10k linijek, nigdy więcej :D

Co do FX'a to dla naprawdę sporych aplikacji narazie nie ma sensu tego ruszać, dopóki nie powstaną frameworki typu Netbeans Platform cz Eclipse RCP.

kostek135   8 #8 28.03.2015 11:47

Beznadziejny wpis:
Więc tak na twój problem z niemożnością kolorowania pojedynczej kolumny na randomowe kolory (jeśli rozszerzone DefaultTCR). Rozszerzam DefaultTCR w sposób anonimowy, c jest bez znaczenia. Kod nie jest ładny bo pisałem go w czasie poniżej minuty (hardkodowany index kolumny, logika wyliczania koloru w CellRenderer, etc.). Można do produkować z 100 linijek i zrobić to jak Bóg przykazał, ale nie bede zaśmiecał komentarza:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class TableTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());

final JTable table = new JTable(3, 3);
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (column != 1) {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}

JPanel pane = new JPanel();
pane.setBackground(randomColor());
return pane;
}
});

JButton btn = new JButton("Change color");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
table.repaint();
}
});

frame.add(table, BorderLayout.NORTH);
frame.add(btn, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}

private static Color randomColor() {
Random rnd = new Random();
return new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
}
}

Kolejne bzdury są o enabled i tego, że trzeba pisać coś sto razy: http://stackoverflow.com/a/10986504

W zasadzie na każdy problem, który przedstawiłeś można na SO znaleźć rozwiązanie, tylko trzeba umieć szukać.

Na miejscu autora wziąłbym ten wpis i spuścił w kiblu, bo tyle jest wart.

kostek135   8 #9 28.03.2015 12:19

@Airborn: Podejrzewam, że Frankfurterium miał na myśli predefiniowany styl, a nie tworzenie swojego LnF od zera.

Frankfurterium   10 #10 28.03.2015 15:31

@kostek135: Oczywiście. Swing domyślnie ma parę swoich uniwersalnych i natywny zależny od systemu. Dodatkowo możemy dorzucać pobrane/zakupione w jarach. Zdarzało mi się delikatnie modyfikować istniejące style, ale nigdy nie porywałbym się na pisanie własnego.

Autor edytował komentarz.
Airborn   8 #11 28.03.2015 16:39

Ja w zasadzie też nie, wszystko bazowało na Synth'u ;) Kwestia ilu przeróbek trzeba by produkt wyglądał tak jak 'powinien'

Druedain   14 #12 28.03.2015 16:49

@kostek135: Przecież ty nawet nie chcesz poważnie rozmawiać…

@awangardowy: Tak jak pisał @Frankfurterium – po co Java na desktopie, na którym coraz słabiej się trzyma?

Jusko   13 #13 28.03.2015 17:19

@Druedain #12: W moim przypadku - do pisania małych programików, usprawniających codzienne czynności (najczęściej nakładki na Linuksowy terminal) ;-)

Idea "napisz raz, uruchom gdziekolwiek" ma sens, bo przecież dzięki temu można stworzyć multum cross-platformowego softu(!). Tylko coś po drodze się wypaliło ;-P

Aczkolwiek fakt, że coraz ciężej utrzymać się z Javą na desktopie - widać, że ten kierunek nie jest priorytetem.

Java ma pewien sens dla chcących wskoczyć kiedyś do J2EE lub Androida, ale do stricte desktopowych aplikacji chyba lepiej nada się Python + Qt - nie ma problemów z fajnymi bibliotekami do wszystkiego, kiedy w Javie zaczyna się / zaczęła dawno posucha. Osobiście jestem nieco na rozdrożu - Java do desktopu, czy jednak Python i Qt, ale logika nakazuje ewakuację w stronę węża.

Autor edytował komentarz.
Frankfurterium   10 #14 28.03.2015 18:04

@Jusko: "Write once, debug everywhere" ;-)

Druedain   14 #15 28.03.2015 18:07

@mistrz_toaletowy (niezalogowany): Sorry, co nie? Niestety u mnie w pracy rzetelność jest mile widziana :-( .

Swoją drogą gdzieś ty widział studentów znających wzorce projektowy, bądź czytających książki? ^_^

@Jusko: Rany, w Javie??? :D

Jeśli chcesz znać moje zdanie, to ja bym szedł w Qt + … Python?

kostek135   8 #16 28.03.2015 18:49

@Druedain: (#12) Oczywiście, że nie chcę, bo nie mamy o czym. Po prostu zostawiam mój komentarz dla potomnych, co by wiedzieli, że ten wpis to głównie stek bzdur, które ni jak mają się do rzeczywistości i wynikają z tego, że autor nie potrafi używać narzędzia. Dzięki temu być może unikniemy ludzi, którzy powtarzają te głupoty.

PS Śmiesznie wyszło z tym "Kłamczuskiem" w tytule. To chyba jest definicja ironii losu, czyż nie?

Autor edytował komentarz.
Druedain   14 #17 28.03.2015 19:51

@kostek135: Więc po co kolejny komentarz?

  #18 30.03.2015 23:11

@MaXDemage: jakies 2 lata temu poprawialem program. W COBOLU z tego co when pracuje do dzis ale kto tu wie co to jest COBOL?

koneton   6 #19 31.03.2015 00:17

@Druedain: to, że nie potrafisz iterować kolekcji i wywołać dla poszczególnych elementów jakieś metody słabo świadczy o Twoich umiejętnościach. Swing może nie jest idealny, ale widziałem wiele aplikacji w nim napisanych. Ich czytelność i łatwość utrzymania zależała głównie od jakości pracy programistów, a nie użytych wzorców...

Druedain   14 #20 31.03.2015 11:05

@koneton: Utnijmy dyskusję związaną z iterowaniem. Popełniłem bardzo prosty błąd. Trudno, zdarza się. Jak będę mieć czas, to poprawię wpis. Czy to wszystko co masz mi do powiedzenia?

koneton   6 #21 31.03.2015 21:09

@Druedain
A co tu pisać? Nie znasz Swinga, zabrałeś się do niego, oczekując czegoś, czego tam nie ma. Brakowało Ci dobrej obsługi modelu? W czasie, który poświęciłeś na szukanie, pewnie byś już napisał coś, co go zastąpi.

@Anonim
COBOL ma się bardzo dobrze. Jeszcze wiele systemów na nim funkcjonuje i pewnie minie wiele lat nim zniknie...

Druedain   14 #22 01.04.2015 10:08

@koneton: Przepraszam, ale skąd ty wiesz to wszystko o mnie??? Przeczytałeś takie rzeczy w tym wpisie, może?

Autor edytował komentarz.
koneton   6 #23 01.04.2015 19:09

@Druedain: Tak. Osoba znająca Swing nie ma takich problemów. Osoba znająca i używająca Swing ma już odpowiednie klasy pomocnicze dawno napisane.

Druedain   14 #24 02.04.2015 11:53

@koneton: Nie, ty nie rozumiesz pytania. Skąd ty wiesz cokolwiek o mnie, o tym co ja mam, czego używam, jak wygląda moja praca??? Gdzie we wpisie masz napisane cokolwiek pokazujące tworzony przeze mnie w pracy kod??? Podpowiem Ci, że jest to pytanie retoryczne, na które z założenia nie udziela się odpowiedzi, ze względu na założenie, że odpowiedź jest oczywista.

Autor edytował komentarz.
koneton   6 #25 02.04.2015 18:17

@Druedain: Twoje problemy lepiej opisują Twoją wiedzę i umiejętności, niż gdybyś napisał to wprost.

Druedain   14 #26 03.04.2015 12:57

@koneton: Przepraszam, jakie moje problemy? A jak czytasz książki fantasy, to wytykasz autorowi nietrzymanie się praw fizyki? Proszę Cię…
Tekst napisałem celowo stosując pewną konwencję. Jeśli tego nie dostrzegasz, nic na to nie poradzę. Jakiekolwiek wysnuwane przez Ciebie sugestie są nie na miejscu.

Autor edytował komentarz.