Java jako j¦zyk modularny Robert A. Kªopotek [email protected] Wydziaª Matematyczno-Przyrodniczy. Szkoªa Nauk cisªych, UKSW 10.03.2017 Kontrola dost¦pu "Kontrola dost¦pu (tudzie» ukrywanie informacji) sprowadza si¦ do poprawiania tego, co nie udaªo si¦ za pierwszym razem" refaktoryzacja kodu - polega na jego przepisywaniu tak, aby byª czytelniejszy, bardziej zrozumiaªy, ªatwiejszy do ogarni¦cia i przyszªej konserwacji niekiedy pojawiaj¡ si¦ gªosy przeciwko refaktoryzacji sugeruj¡ce, ze kod dziaªaj¡cy to kod dobry i dªubanie w nim to strata czasu lwia cz¦±¢ nakªadów czasowych i nansowych w projektach to nie ich powstanie a utrzymanie kod spaghetti - "termin okre±laj¡cy skomplikowany, trudny do zrozumienia kod ¹ródªowy programu. Z takiego kodu skompilowano wiele programów w starszych j¦zykach proceduralnych, typu Fortran czy BASIC. Byªo to jeszcze przed powstaniem metody programowania strukturalnego." 2 / 25 Kod spaghetti kojarzy si¦ gªównie z dªugimi, popl¡tanymi procedurami napisanymi bardzo dawno temu pierwszym symptomem kodu spaghetti jest sama dªugo±¢ kodu, kilkana±cie, kilkadziesi¡t tysi¦cy linii kodu, ogromna ilo±¢ rozgaª¦zie« utrudnia poruszanie si¦ po takim kodzie. standardowo dªugo±¢ jednej jednostki programowej nie powinna wykracza¢ poza ekran monitora (zalecane maksymalnie 50-80 linii) nie tylko dªugi kod to spaghetti - np. metoda, która podbija licznik, a potem usuwa dane z tablicy niezwi¡zanej z licznikiem dzielenie kodu na mniejsze jednostki programowe 3 / 25 Kod spaghetti - przykªady Pakiet 1: generate _le Procedury: Main_le , Start _le , Run_le , Gen_le Ile wiemy po przejrzeniu specykacji pakietu? Szczerze mówi¡c niewiele. Jedne co wiemy, to »e procedury generuj¡ jaki± plik. Ale która procedura odpowiada za jak¡ funkcjonalno±¢ w procesie? Pakiet 2: generate _le Procedury: Main, Get _lename , Get _data, Open_le , Create _line , Save _line , Close _le W powy»szym pakiecie b¦dzie du»o ªatwiej si¦ porusza¢. Ju» na pierwszy rzut oka mamy rozeznanie, jakie zadania wykonuje proces i która procedura odpowiada za jak¡ czynno±¢ podczas generowania pliku. 4 / 25 Dobre praktyki 1 Nazwy jednostek programowych powinny by¢ precyzyjne, odzwierciedlaj¡ce funkcjonalno±¢ procedury 2 Kod powinien mie±ci¢ si¦ na ekranie 3 Podziaª programu na mniejsze jednostki powinien odbywa¢ si¦ wedªug zasady "od ogóªu do szczegóªu" a nie na chybiª traª 4 Ilo±¢ wyj±¢ z programu powinna wynosi¢ 1. 5 Skomplikowane algorytmy, warunki if nale»y schowa¢ za wyspecjalizowanymi funkcjami 6 Nale»y unika¢ przerwa« p¦tli lepiej dostosowa¢ typ p¦tli do typu problemu 5 / 25 Projektowanie biblioteki (1/2) pierwsz¡ spraw¡ bran¡ pod uwag¦ w programowaniu obiektowym jest "oddzielenie rzeczy, które si¦ zamieniaj¡ od rzeczy, które si¦ nie zmieniaj¡" jest to szczególne istotne w przypadku bibliotek - u»ytkownicy biblioteki musza polega¢ na cz¦±ci, która wykorzystuj¡ i nie obawia¢ si¦, »e b¦d¡ musieli przepisywa¢ kod, je»eli pojawi si¦ nowa wersja twórca biblioteki - ma swobod¦ w jej modykacji i ulepszania przy zachowaniu pewno±ci, »e zamiany nie b¦d¡ miaªy wpªywu na kod u»ytkowników, np. caªkowita zmiana funkcjonalno±ci, zmiana typu zwracanego wyniku itp. mo»na to osi¡gn¡¢ poprzez ustalenie konwencji - interfejs programistyczny aplikacji/biblioteki (ang. Application Programming Interface, API) 6 / 25 Projektowanie biblioteki (2/2) w Javie rozwi¡zaniem s¡ modykatory dost¦pu, które umo»liwiaj¡ twórcom biblioteki zaznaczenie, co ma by¢ dost¦pne a co nie dla u»ytkownika projektant biblioteki powinien wszystko, co si¦ da, uczyni¢ prywatnym (modykator private), a eksponowa¢ jedynie to, co powinno by¢ wykorzystywane przez u»ytkowników komponenty aplikacji ª¡czone s¡ w jednostki biblioteczne przez sªowo kluczowe package (pakiet) na modykatory dost¦pu ma wpªyw to czy s¡ w tym samym pakiecie czy w ró»nych (np. modykator domy±lny - patrz poprzedni wykªad) 7 / 25 Pakiet - jednostka biblioteczna Pakiet - grupa klas zebranych razem we wspólnej przestrzeni nazw biblioteka narz¦dziowa Javy: java.util // plik PelnaNazwa . java class PelnaNazwa { public static void main ( String [] args ){ java . util . ArrayList list = new java . util . ArrayList (); } } // plik Importowanie . java import java . util . ArrayList ; class Importowanie { public static void main ( String [] args ){ ArrayList list = new ArrayList (); } }8 / 25 Dlaczego importowanie? dostarczenie mechanizmu zarz¡dzaniem przestrzeniami nazw nazwy skªadników s¡ od siebie odizolowane metoda f() klasy A nie wejdzie w konikt z metod¡ f() klasy B mimo tej samej sygnatury pakiet domy±lny (pakiet nienazwany) - rozwi¡zanie tylko na pocz¡tku nauki Javy je±li planujemy tworzenie bibliotek, musimy zapobiec koniktom nazw! 9 / 25 Jednostka kompilacji jednostka kompilacji (jednostka translacji) - plik z kodem ¹ródªowym Java nazwa ka»dej jednostki kompilacji musi mie¢ rozszerzenie .java wewn¡trz jednostki kompilacji mo»e znajdowa¢ si¦ klasa publiczna, której nazwa musi by¢ taka sama jak nazwa pliku w ka»dej jednostce mo»e znajdowa¢ si¦ tylko jedna klasa publiczna ewentualne inne klasy wchodz¡ce w skªad jednostki kompilacji s¡ ukryte przed ±wiatem zewn¦trznym, stanowi¡ one "klasy wspieraj¡ce" zamieszczonej gªównej klasy publicznej 10 / 25 Organizacja kodu po kompilacji pliku .java, otrzymujemy dla ka»dej klasy z pliku plik o takiej samej nazwie ale z rozszerzeniem .class w ogólno±ci z jedno pliku .java mo»emy otrzyma¢ kilka plików .class dziaªaj¡cy program to zbiór plików typu .class, które mog¡ zosta¢ spakowane programem archiwizuj¡cym do typu .jar interpreter Javy (java.exe) odpowiada za znajdowanie, ªadowanie i interpretowanie tych plików istniej¡ równie» kompilatory produkuj¡ce plik wykonywalny dla danej platformy sprz¦towej (kompilacja podobna do C/C++) 11 / 25 Budowanie biblioteki Biblioteka stanowi zespóª plików zawieraj¡cych klasy je±li chcemy zaznaczy¢, »e komponenty (.java i .class) stanowi¡ jedn¡ caªo±¢, u»ywamy sªowa kluczowego package je±li stosujemy instrukcj¦ package to musi by¢ ona jako pierwsza w pliku (poza ewentualnymi komentarzami) instrukcja package moj_pakiet; oznacza, ze ta jednostka kompilacji znajduje si¦ w przestrzeni nazw moj_pakiet, wi¦c ka»dy, kto chciaªby wykorzysta¢ zawarte w niej nazwy, musi albo u»y¢ peªnej nazwy, albo u»y¢ instrukcji import z nazwa pakietu moj_pakiet 12 / 25 Budowanie biblioteki - przykªad // plik rak / moj_pakiet / MojaKlasa . java package rak . moj_pakiet ; public class MojaKlasa { // ... } // plik rak / PelnaNazwa . java public class PelnaNazwa { public static void main ( String [] args ){ rak . moj_pakiet . MojaKlasa m = new rak . moj_pakiet . MojaKlasa (); } } // plik rak / Importowanie . java import rak . moj_pakiet .*; public class Importowanie { public static void main ( String [] args ){ MojaKlasa m = new MojaKlasa (); } }13 / 25 Tworzenie unikatowych nazw pakietów aby organizowa¢ wiele plików wynikowych .class skªadaj¡cych si¦ na dany pakiet, mo»na umie±ci¢ je w jednym katalogu je±li mamy wiele pakietów to otrzymujemy hierarchi¦ katalogów zgodnie z konwencja przyjmuje si¦, »e pierwsza cz¦±¢ nazwy pakietu powinna stanowi¢ odwrócona nazwa domeny internatowej twórcy, poniewa» unikatowo±¢ domen internetowych jest gwarantowana i unikniemy koniktu nazw przykªad: dla mojej domeny rklopotek.blog.uksw.edu.pl przed ka»d¡ nawz¡ powinno si¦ znale¹¢ pl.edu.uksw.blog.rklopotek interpreter szuka klas z danego pakietu przechodz¡c drzewo katalogów rozdzielone kropkami, dlatego w przykªadzie pakiet MojaKlasa z pakietu rak.moj_pakiet znajduje si¦ na ±cie»ce rak/moj_pakiet/MojaKlasa.class 14 / 25 Przestrzenie nazw aby uruchomi¢ program znajduj¡cy si¦ w klasie MojaKlasa z konsoli, nale»aªoby przej±¢ do katalogu rodzica i wykona¢ polecenie java rak.moj_pakiet.MojaKlasa co si¦ dzieje, gdy program importuje dwie biblioteki zawieraj¡ce te same nazwy? w C/C++ "DLL Hell" - termin na komplikacje, które pojawiaj¡ si¦ przy korzystaniu z bibliotek dynamicznych stosowanych w systemach operacyjnych Microsoft Windows, szczególnie w odziedziczonej wersji 16-bitowej, w której wszystkie aplikacje dziaªaj¡ we wspólnej przestrzeni adresowej. Obecnie problem nie jest ju» tak dotkliwy dzi¦ki wprowadzeniu .NET Framework, Registration-Free COM i funkcjonalno±ci zapobiegaj¡cej nadpisaniu plików systemowych. w Java ten problem nie istnieje je±li nast¡pi kolizja nazw, kompilator zaprotestuje i wymusi zastosowanie tzw. peªnej nazwy 15 / 25 Wªasna biblioteka narz¦dziowa biblioteki narz¦dziowe zwykle zawieraj¡ klasy z szeregiem metod statycznych, np. java.io.* (System.out.printl) czy java.util.* (klasy zwi¡zane z kolekcjami, takimi jak listy, mapy, zbiory, iteratory, komparatory, itp.) w j¦zyku C/C++ istnieje kompilacja warunkowa pozwalaj¡ca na uzyskanie innego zachowania za pomoc¡ przeª¡cznika bez zmienienia reszty kodu. Rozwi¡zanie byªo gªównie wykorzystywane do przenoszenia kodu, np. #if _WIN64 czy #if __GNUC__ kompilacja warunkowa nie istnieje w j¦zyku Java ze wzgl¦du na przeno±no±¢ kodu - raz skompilowany kod b¦dzie dziaªa na innych platformach 16 / 25 Kompilacja warunkowa istniej¡ jednak przydatne zastosowania tego podej±cia, np. podczas projektu dobrzej jest wypisywa¢ informacje debug a w produkcji klasa nie powinna wypisa¢ takich rzeczy - wystarczy do zmiennej CLASSPATH doda¢ odpowiedni¡ wersj¦, która ró»ni si¦ np. wypisywaniem komunikatów je±li chodzi o sam kod to kompilator optymalizuje nieu»ywany kod, aby wymusi¢ usuni¦cie danego fragmentu wystarczy wstawi¢ zmienn¡ steruj¡c¡ static final, np.: static final boolean DEBUG = false ; if ( DEBUG ) { // some code .... } 17 / 25 Konwencje nazewnictwa Klasy i interfejsy - pierwsza litera nazwy klasy, lub interfejsu musi by¢ du»a, a pozostaªe litery maªe Metody - metody zaczyna maªa litera, nast¦pne zgodnie z "camelCase" Zmienne - pierwsza litera maªa, a kolejne zgodnie z "camelCase" Staªe - staªe w Javie oznaczane s¡ poprzez "static" oraz "nal". Nazwy staªych powinny by¢ pisane wielkimi literami, z podkre±leniem "_", je»eli nazwa skªada si¦ z wielu czªonów Pola klas je±li pole klasy nie jest typu logicznego (boolean), metoda zwracaj¡ca jej warto±¢ powinna zaczyna¢ si¦ od sªowa "get", musi by¢ publiczna, bezparametrowa je±li pole klasy jest typu logicznego, metoda zwracaj¡ca jej warto±¢, powinna zaczyna¢ si¦ od sªowa "is" metoda ustawiaj¡ca warto±¢ pola klasy powinna zaczyna¢ si¦ od sªowa 18 / 25 "set", musi by¢ publiczna, typu void Pakowanie bibliotek - zalety JAR bezpiecze«stwo - istnieje mo»liwo±¢ podpisania cyfrowego pliku JAR zmniejszony czas pobierania - je±li biblioteka JAR jest cz¦±ci¡ aplikacji webowej kompresja danych - kompresja JAR wykorzystuje algorytm ZIP opakowanie do rozszerzania - w prosty sposób mo»na dodawa¢ funkcjonalno±¢ przez skopiowanie do projektu jednego pliku a nie caªej hierarchii katalogów zapiecz¦towanie pakietu - JAR mo»e wymusi¢ spójno±¢ wersji pakietu, klasy zdeniowane w tym pakiecie musz¡ znajdowa¢ si¦ w tym samym pliku JAR wersjonowanie pakietów przeno±no±¢ - biblioteka lub aplikacja prosta do uruchomienia, np. H2 SQL server 19 / 25 Podstawy JAR tworzenie pliku JAR jar cf jar-file input-file(s) ogl¡danie zawarto±ci JAR jar tf jar-file wypakowywanie caªej zawarto±ci JAR jar xf jar-file wypakowywanie niektórych plików w archiwum JAR jar xf jar-file archived-file(s) uruchamiania aplikacji zapakowanej w archiwum JAR java -jar app.jar 20 / 25 Podstawy JAR pakowanie struktury: jar cvf TicTacToe.jar TicTacToe.class audio images pakowanie bez kompresji: jar cvf0 TicTacToe.jar TicTacToe.class audio images pakowanie zawarto±ci katalogu: jar cvf TicTacToe.jar * plik META-INF/MANIFEST.MF zawiera Main-Class: classname nazw¦ klasy, któr¡ nale»y uruchomi¢ z polecenia java -jar app.jar 21 / 25 Plik manifestu zawiera informacje o pliku JAR: klas¦ do uruchomienia, wersj¦, kompilator, podpis cyfrowi, itp. znajduje si¦ w zawsze w META-INF/MANIFEST.MF domy±lna warto±¢ (dla wersji JDK 1.7.0_06): Manifest - Version : 1.0 Created - By : 1.7.0 _06 ( Oracle Corporation ) zmiana pliku manifestu: jar cfm jar-file manifest-addition input-file(s) zawarto±¢ manifestu musi mie¢ kodowanie UTF-8 22 / 25 Plik manifestu - przykªad niech plik manifestu ma nazw¦ Manifest.txt i zawiera lini¦ Main-Class: MyPackage.MyClass wtedy mo»emy utworzy¢ plik JAR z tym manifestem poleceniem jar cfm MyJar.jar Manifest.txt MyPackage/*.class to utworzy plik o zawarto±ci: Manifest - Version : 1.0 Created - By : 1.7.0 _06 ( Oracle Corporation ) Main - Class : MyPackage . MyClass wtedy po uruchomieniu JAR java -jar MyJar.jar wystartuje metoda main w klasie MyClass 23 / 25 Zdeniowanie wersji - przykªad niech plik manifestu ma nazw¦ Manifest.txt i zawiera: Name : java / util / Specification - Title : Java Utility Classes Specification - Version : 1.2 Specification - Vendor : Example Tech , Inc . Implementation - Title : java . util Implementation - Version : build57 Implementation - Vendor : Example Tech , Inc . wtedy za pomoc¡ polecenia jar cfm MyJar.jar Manifest.txt MyPackage/*.class wgramy ten manifest do pliku JAR 24 / 25 Pytania? 25 / 25