Robert Strack [email protected] Style Kodowania formatowanie kodu konwencje nazewnicze konwencje programistyczne dokumentowanie kodu struktura projektu używanie pakietów logowanie pliki JAR Formatowanie kodu Uwagi ogólne pliki źródłowe nie powinny zawierać więcej niż 2000 linii kodu - zwiększa to przejrzystość struktury programu i przyspiesza wyszukiwanie interesujących nas fragmentów każda linia powinna się mieścić w oknie edytora (standardowo 80 znaków) - łatwiej zrozumieć wyrażenia, które da się objąć w całości wzrokiem - przełamany fragment linii należy poprzedzić szerokim wcięciem public static void copyFile(String source, String destination) { /* do something */ } robiąc wcięcia, sugerowane jest, aby nie używać znaków spacji (zamiast tego lepiej użyć tabulatora) - dzięki temu osoba pracująca z naszym kodem w innym edytorze może dostosować szerokość odstępów nie ingerując w nasz kod, ale jedynie poprzez zmianę domyślnej szerokości tabulacji - większe wcięcia zwiększają czytelność kodu Formatowanie kodu Białe znaki mile widziana jest spacja po przecinkach w liście parametrów funkcji - zwiększa to czytelność deklaracji umieszczanie spacji pomiędzy nazwą funkcji i okrągłymi nawiasami zmniejsza czytelność public static int addNumbers(int first, int second) { return first + second; } podczas wykonywania działań należy rozdzielać zmienne od operatorów result = (variable1 + variable2) / variable3; odstęp powinien się również znaleźć w instrukcji rzutowania BaseClass myClass = (BaseClass) yourClass; Formatowanie kodu Instrukcje sterujące konstrukcja instrukcji „if” if (condition) { statements; } - mile widziane jest używanie nawiasów klamrowych po „if”, nawet jeśli nie są one wymagane if (condition) { statements; } else { statements; } Formatowanie kodu konstrukcja pętli „do” i „do-while” while (condition) { statements; } do { statements; } while (condition); konstrukcja pętli „for” for (initialization; condition; update) { statements; } Instrukcje sterujące Formatowanie kodu Instrukcje sterujące konstrukcja instrukcji „switch” - jeżeli po „case” nie zamierzamy wstawić instrukcji „break” należy to zaakcentować komentarzem - wewnątrz każdej instrukcji „switch” powinna się znaleźć opcja „default” (może być pusta) switch (condition) { case ONE: statements; /* falls through */ case TWO: statements; break; default: statements; break; } Formatowanie kodu Instrukcje sterujące przechwytywanie wyjątków - nie należy pozostawiać nie obsłużonych wyjątków try { statements; } catch (Exception ex) { statements; } finally { statements; } „return” nie jest funkcją, więc nie należy stawiać po nim nawiasów - użycie nawiasów jest wskazane, jeśli wyrażenie zwracane przez funkcje jest skomplikowane return value; return ((a > b) ? a : b); Formatowanie kodu Deklaracje każda zmienna powinna być deklarowana w nowej linii - długie deklaracje nie są przejrzyste MyClass myObject1; MyClass myObject2; deklaracje metod powinny zawierać informacje o rzucanych wyjątkach - w języku JAVA wymusza to kompilator! public void doSomething() throws Exception { statements; } liczba argumentów funkcji nie powinna być zbyt duża - funkcje takie są niewygodne w użyciu Formatowanie kodu Nazwy nazwy klas i interfejsów powinny się rozpoczynać wielką literą tak samo każde słowo składające się na nazwę; niewskazane jest używanie separatorów class MyClass extends YourClass { /* body */ } nazwy metod i zmiennych rozpoczyna się mała literą, występujące dalej słowa pisze się już wielką literą - wyjątkiem są konstruktory, które mają nazwę identyczną z nazwą klasy public int getDifference(int a, int b) { int value = a – b; return value; } dla stałych używa się wyłącznie wielkich liter i separatorów (podobnie jak w C) final int CONST_VALUE = 100; Formatowanie kodu Nazwy do tworzenia nazw pakietów używa się wyłącznie małych liter, bez separatora „_” - przypominają odwrócony adres internetowy package domain.company.project.module; - duże litery mogą wystąpić tylko w nazwach klas import java.applet.Applet; Formatowanie kodu Dodatkowe konwencje nie powinno się używać zmiennych zadeklarowanych jako public (chyba, że public static final) zamiast tego można (trzeba) deklarować metody typu get/set - metody te nie powinny nic robić poza zwracaniem i ustawianiem wartości public void setName(String name) { this.name = name; } public String getName() { return name; } public bool isActive() { return active; } Formatowanie kodu Dodatkowe konwencje wszelkie „gotowe” wartości liczbowe powinny być umieszczane w kodzie jako stałe - pozwoli nam to w przyszłości szybko wprowadzać modyfikacje oraz zwiększy czytelność kodu wewnątrz konstruktorów (i funkcji typu set) dobrze jest używać konstrukcji w stylu „this.variable = variable” public MyClass(String name) { this.name = name; } w dobrym stylu jest przeładowywać metody dziedziczone z klasy Object (np. toString(), equals()) public String toString() { return („My name is: ” + name + surname); } importując pakiety powinno się użyć nazwy konkretnej klasy (zamiast „*”) import java.applet.Applet Dokumentowanie kodu Dokumentacja tworzenie dokumentacji jest niezbędne w każdym większym projekcie informatycznym - dzięki temu możemy sobie szybciej przypomnieć, w jaki sposób zachowują się nasze klasy oraz umożliwić analizę kodu osobom trzecim dokumentacja powinna być pisana w języku angielskim - zapewni to spójność z istniejącymi standardami (np. javadoc) komentarze powinny dotyczyć klas, interfejsów, zmiennych i metod dobrze jeśli komentarze są tworzone na bieżąco składnia komentarzy /* comment */ - komentarz mogący się rozciągać na wiele wierszy // comment - komentarz w jednym wierszu /** comment */ - komentarz javadoc (javadoc pomija każdy inny komentarz!) Dokumentowanie kodu Dokumentacja najważniejsze znaczniki dokumentacyjne - są umieszczane wewnątrz komentarzy, na ich podstawie tworzona jest dokumentacja przez program javadoc @see MyClass @see MyClass#methodFromMyClass @version description @author my-name @param paramether description @return description @throws what description @deprecated w dokumentacji wygenerowanej przez javadoc w tym miejscu zostaną umieszczone odnośniki do „MyClass” i metody „methodFromMyClass” opis wersji autor parametry wartość zwracana typy rzucanych wyjątków Sugeruje by nie używać danej właściwości (w przyszłości może zostać usunięta) Dokumentowanie kodu Dokumentacja komentowanie klas - powinien się znaleźć komentarz o relacjach klasy z innymi klasami (@see), informacje o autorach (@author) i wersji (@version) komentowanie metod - opisany powinien być sposób działania metody, odwołania do innych metod (@see), przyjmowane parametry (@param),rzucane wyjątki (@throws) i wartość zwracana (@return) nagłówki plików - każdy plik projektu powinien zaczynać się informacją o swojej zawartości dodatkowe komentarze - jeżeli instrukcjom języka JAVA będą towarzyszyć słowne informacje o działaniu zastosowanych algorytmów, przyszła analiza budowy metod i klas będzie łatwiejsza Dokumentowanie kodu Dokumentacja przykład dokumentowania // HelloWorld.java // Writes „Hello World!” onto screen import java.lang.System; /** My first class in JAVA * @author Robert Strack * @author [email protected] * @version 1.0 */ public class HelloWorld { /** Function only says „Hello World!” * @param args String used for holding parameters * @return Nothing */ public static void main(String[] args) { System.out.println(„Hello World!”); } } Dokumentowanie kodu przykład dokumentowania (gotowa dokumentacja przy użyciu javadoc) Dokumentacja Struktura projektu Struktura katalogów struktura katalogów powinna wyglądać następująco: Struktura katalogów projektu opt oprogramowanie niezbędne w procesie kompilowania i instalowania oprogramowania (jdk, ant, jikes) src katalog z plikami źródłowymi projektu build.bat plik przygotowujący środowisko projektu (ustawienie odpowiednich zmiennych środowiskowych, uruchomienie ant’a) build.xml plik konfiguracyjny programu ant src/config pliki konfiguracyjne projektu src/database skrypty bazodanowe projektu src/docs dokumentacja projektowa i inne dokumenty związane z projektem src/etc pliki deployment descriptor src/resources pliki resource deployment descriptor dla iAS src/tlds pliki tag lib descriptiors src/java pliki źródłowe Javy src/test pliki źródłowe Javy dla testów src/web pliki html, jsp, gif, jpeg lib dodatkowe biblioteki jar i zip build katalog tymczasowy dla skompilowanych źródeł Javy oraz dokumentacji Javadoc assembly katalog tymczasowy dla plików war, jar, ear dist katalog tymczasowy z dystrybucją projektu Pakiety Wykorzystywanie pakietów pakiet – jest to zbiór klas i interfejsów z kontrolą dostępu do nich i własną przestrzenią nazw (odpowiednik biblioteki w C) zamieszczając klasy w pakiecie: - możemy zaznaczyć, że są one ze sobą powiązane - ich nazwy nie wchodzą w konflikt z nazwami innych klas - pakiet posiada własną przestrzeń nazw - możemy pozwolić, aby klasy z naszego pakietu miały nieograniczony dostęp do siebie nawzajem i jednocześnie były niewidoczne dla klas spoza pakietu (ukrywanie implementacji) - poprzez pakiety budujemy logiczną strukturę projektu Pakiety Tworzenie pakietów w celu dołączenia klasy (klas) do pakietu używamy konstrukcji package name.of.this.package; - instrukcja powinna być podana przed definicjami klas (na początku pliku) aby użyć klas lub interfejsów wchodzących w skład pakietu posługujemy się konstrukcją import name.of.this.package; - instrukcja powinna być podana przed definicjami klas (na początku pliku) jeden plik może zawierać dowolną ilość klas, ale tylko jedna z nich może być zadeklarowana jako „public” klasy nie zadeklarowane jako publiczne nie są widoczne poza pakietem Pakiety Tworzenie pakietów do klasy znajdującej się w zaimportowanym pakiecie możemy się odwołać przez jej nazwę, lub podając pełną nazwę pakietu z którego klasa pochodzi + nazwę klasy String name; java.lang.String name; - dzięki temu pojawienie się dwóch klas o identycznych nazwach, ale zawartych w innych pakietach nie jest problemem (klasy te są rozróżnialne) Logowanie Rejestracja rejestracja polega na tworzeniu i gromadzeniu informacji o wykonującym się programie (najczęściej w celu usunięcia błędów lub zwiększenia wydajności) - informacje można wypisywać wstawiając w kod programu wywołania procedur System.out.println(), ale taki sposób rejestracji nie jest wygodny - zamiast tego można użyć klasy java.util.logging.Logger przewaga „logowania” nad zwykłym wypisywaniem informacji do pliku, czy na ekran: - jeżeli program już działa poprawnie nie potrzebujemy usuwać linii w których rejestrowaliśmy komunikaty o przebiegu jego działania... wystarczy, że wyłączymy Logger’a (występowanie wywołań metod klasy Logger nie spowolni pracy programu) - możemy w łatwy sposób zmieniać sposób rejestrowania (wypisanie na ekran, do pliku a nawet wysłanie mailem!) - istnieje możliwość filtrowania komunikatów ze względu na ich wagę Logowanie Rejestracja każda wiadomość ma przypisaną wagę (poziom): - SEVERE - WARNING - INFO - CONFIG - FINE - FINER - FINEST - dodatkowo poziomy OFF i ALL (do włączania i wyłączania rejestracji) ustawiając poziom logowania dla konkretnego obiektu klasy Logger możemy przefiltrować wiadomości jakie dla nas rejestruje Logger logger = Logger.getLogger(„logger name”); logger.setLevel(Level.INFO); logger.warning(„warning”); logger.info(„information”); logger.fine(„other information”); - w powyższym przykładzie wypisana zostanie informacja „information” i „warning” (wypisywane są informacje o poziomie równym lub wyższym od ustalonego) Logowanie Rejestracja aby zmienić sposób rejestracji (np. skierować informacje do pliku) należy się posłużyć klasą Handler (i klasami po niej dziedziczącymi) Logger logger = Logger.getLogger(„logger name”); logger.addHandler(new FileHandler(„file.xml”)); logger.info(„information”); - informacja zostanie zapisana do pliku file.xml - inne klasy pochodne od klasy Handler: ConsoleHandler, MemoryHandler... jeżeli chcemy zapisywać wyniki w zwykłym pliku tekstowym, dodatkowo trzeba się posłużyć obiektem klasy Formatter (lub po niej dziedziczącym) Logger logger = Logger.getLogger(„logger name”); logger.setFormatter(new SimpleFormatter()); logger.addHandler(new FileHandler(„file.txt”)); logger.info(„information”); Logowanie Rejestracja możliwe jest oczywiście rozbudowywanie funkcji klas Formatter (klasy formatującej dane), Handler (klasy obsługującej magazynowanie danych) i Filter (klasy zajmującej się filtrowaniem informacji) poprzez dziedziczenie – stworzenie tym samym w pełni odpowiadającego nam systemu rejestracji pakiet java.util.logging zawiera jeszcze wiele przydatnych funkcji – są one opisane w dokumentacji Logowanie Rejestracja podobne możliwości daje nam pakiet org.apache.log4j - używa się go podobnie jak pakietu java.util.logging Logger logger = Logger.getLogger(„logger name”); logger.setLevel(Level.INFO); logger.info(„information”); log4j daje nam duże możliwości konfiguracji - wewnątrz kodu programu BasicConfigurator.configure(); automatyczna konfiguracja (poziomy logowania są ustawiane na domyślne wartości) - za pomocą pliku konfiguracyjnego PropertyConfigurator.configure(„configuration.conf”); zostanie użyty plik konfiguracyjny „configuration.conf” Logowanie Rejestracja przykład budowy pliku konfiguracyjnego # ustawiamy poziomu logowania na DEBUG # chcemy, aby rejestrowane wiadomości były wyświetlane # na ekranie i zapisywane do pliku log4j.rootLogger = DEBUG, screen, file # „screen” służy do wypisywania wiadomości na ekran log4j.appender.screen = org.apache.log4j.ConsoleAppender # ustalamy sposób wypisywania (data, priorytet i wiadomość) log4j.appender.screen.layout = org.apache.log4j.PatternLayout log4j.appender.screen.layout.ConversationPattern = „[%d] %p: %m” Logowanie Rejestracja przykład budowy pliku konfiguracyjnego (cd.) # identycznie konfigurujemy sposób zapisywania do pliku log4j.appender.file = org.apache.log4j.RollingFileAppender log4j.appender.file.layout = org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversationPattern = „[%d] %p: %m” # zapisywać informacje będziemy w „file.log” log4j.appender.file.File = file.log # maksymalna wielkość pliku log4j.appender.file.MaxFileSize = 10KB # niech zapisuje tylko do jednego pliku log4j.appender.file.MaxBackupIndex = 1 Archiwa JAR Użytkowanie JAVA Archive archiwa JAR zawierają skompresowane pliki niezbędne do prawidłowej pracy programu - są to nie tylko pliki „*.class”, ale również pliki zawierające grafikę lub dźwięk - dzięki temu cały program mieści się w jednym archiwum tworzenie archiwów JAR: jar cvf file.jar input_files c – stwórz archiwum f – z pliku (nie z wiersza poleceń!) v – wyświetl dokładny opis 0 – (zero) bez kompresji przeglądanie archiwów JAR: jar tvf file.jar t – lista zawartości f – z pliku (nie z wiersza poleceń!) v – wyświetl dokładny opis Archiwa JAR Użytkowanie JAVA Archive wypakowywanie archiwów JAR: jar xvf file.jar [what] x – wypakuj f – z pliku (nie z wiersza poleceń!) v – wyświetl dokładny opis uaktualnianie archiwów JAR: jar uvf file.jar new_files u – uaktualnij m – przy okazji uaktualnia „manifest” (są w nim przechowywane informacje o zawartości archiwum) f – z pliku (nie z wiersza poleceń!) v – wyświetl dokładny opis Archiwa JAR Użytkowanie JAVA Archive uruchamianie archiwów JAR: jre -cp file.jar ClassName - uruchamia metodę „main” z klasy „ClassName” java -jar file.jar - wcześniej należy jednak dodać do archiwum informację o tym z której klasy będzie pobierana metoda „main” np.: jar cvmf MainClassFile.conf HelloWorld.jar HelloWorld.class - gdzie plik MainClassFile.conf zawiera linijkę „Main-Class: HelloWorld.class” - stworzy to archiwum JAR o nazwie HelloWorld.jar, zawierające klasę HelloWorld.class, które można uruchomić poleceniem „java –jar” Archiwa JAR Użytkowanie JAVA Archive istnieje możliwość użycia archiwów JAR na stronach internetowych (jako applety) - przyspieszamy tym czas pobierania plików z serwera <applet code=„HelloWorld.class” archive=„HelloWorld.jar” width=100 height=100> </applet>