JavaRush /Java blogi /Random-UZ /Umumiy dasturlash uslubi bo'yicha qo'llanma
pandaFromMinsk
Daraja
Минск

Umumiy dasturlash uslubi bo'yicha qo'llanma

Guruhda nashr etilgan
Ushbu maqola “Kengaytirilgan Java” akademik kursining bir qismidir. Bu kurs Java funksiyalaridan qanday samarali foydalanishni oʻrganishingizga yordam berish uchun moʻljallangan. Material ob'yekt yaratish, raqobat, ketma-ketlashtirish, aks ettirish kabi "ilg'or" mavzularni o'z ichiga oladi. Kurs sizga Java texnikasini samarali o'zlashtirishni o'rgatadi. Tafsilotlar bu yerda .
Tarkib
1. Kirish 2. O‘zgaruvchilar doirasi 3. Sinf maydonlari va mahalliy o‘zgaruvchilar 4. Usul argumentlari va mahalliy o‘zgaruvchilar 5. Boxing va Unboxing 6. Interfeyslar 7. Strings 8. Nomlash qoidalari 9. Standart kutubxonalar 10. O‘zgarmaslik 11. Keyingi Sinov. 12. .. 13. Manba kodini yuklab oling
1.Kirish
Qo'llanmaning ushbu qismida biz Java-da yaxshi dasturlash uslubi va sezgir dizaynning umumiy tamoyillarini muhokama qilishni davom ettiramiz. Biz ushbu tamoyillarning ba'zilarini qo'llanmaning oldingi boblarida ko'rib chiqdik, ammo Java dasturchisining malakasini oshirish maqsadida ko'plab amaliy maslahatlar beriladi.
2. O‘zgaruvchan doirasi
Uchinchi qismda ("Sinflar va interfeyslarni qanday loyihalash kerak") biz ko'rinishdagi cheklovlarni hisobga olgan holda sinflar va interfeyslar a'zolariga ko'rinish va foydalanish imkoniyatini qanday qo'llash mumkinligini muhokama qildik. Biroq, biz usullarni amalga oshirishda ishlatiladigan mahalliy o'zgaruvchilarni hali muhokama qilmaganmiz. Java tilida har bir mahalliy o'zgaruvchi, bir marta e'lon qilingandan so'ng, qamrovga ega. Ushbu o'zgaruvchi e'lon qilingan joydan usulning (yoki kod blokining) bajarilishi tugaguniga qadar ko'rinadi. Umuman olganda, amal qilish kerak bo'lgan yagona qoida - mahalliy o'zgaruvchini u ishlatiladigan joyga iloji boricha yaqinroq e'lon qilish. Oddiy misolni ko'rib chiqaylik: for( final Locale locale: Locale.getAvailableLocales() ) { // блок codeа } try( final InputStream in = new FileInputStream( "file.txt" ) ) { // блока codeа } Ikkala kod bo'lagida ham o'zgaruvchilar doirasi ushbu o'zgaruvchilar e'lon qilingan ijro bloklari bilan cheklangan. Blok tugagach, qamrov tugaydi va o'zgaruvchi ko'rinmas holga keladi. Bu aniqroq ko'rinadi, ammo Java 8-ning chiqarilishi va lambdalarning kiritilishi bilan tilning mahalliy o'zgaruvchilardan foydalanadigan ko'plab taniqli idiomalari eskirib bormoqda. Avvalgi misoldan sikl o‘rniga lambdalardan foydalangan holda misol keltiraman: Arrays.stream( Locale.getAvailableLocales() ).forEach( ( locale ) -> { // блок codeа } ); Siz mahalliy o‘zgaruvchi funktsiyaning argumentiga aylanganini ko‘rishingiz mumkin, bu esa o‘z navbatida forEach usuliga argument sifatida uzatiladi .
3. Sinf maydonlari va mahalliy o'zgaruvchilar
Java'dagi har bir usul ma'lum bir sinfga (yoki Java8 misolida, usul standart usul sifatida e'lon qilingan interfeysga) tegishli. Sinf sohalari yoki amalga oshirishda qo'llaniladigan usullar bo'lgan mahalliy o'zgaruvchilar o'rtasida nomlar to'qnashuvi ehtimoli mavjud. Java kompilyatori mavjud bo'lganlar orasidan to'g'ri o'zgaruvchini qanday tanlashni biladi, garchi bir nechta ishlab chiquvchilar ushbu o'zgaruvchidan foydalanmoqchi bo'lsa ham. Zamonaviy Java IDE-lar kompilyator ogohlantirishlari va o'zgaruvchilarni ajratib ko'rsatish orqali ishlab chiquvchiga bunday nizolar qachon sodir bo'lishini aytib berishda juda yaxshi ish qiladi. Ammo kod yozishda bunday narsalar haqida o'ylash yaxshiroqdir. Men misolni ko'rib chiqishni taklif qilaman: public class LocalVariableAndClassMember { private long value; public long calculateValue( final long initial ) { long value = initial; value *= 10; value += value; return value; } } misol juda oson ko'rinadi, lekin bu tuzoq. HisoblashValue usuli mahalliy o'zgaruvchining qiymatini kiritadi va u bilan ishlaydigan sinf maydonini xuddi shu nom bilan yashiradi. Chiziq value += value; sinf maydoni va mahalliy o'zgaruvchining qiymati yig'indisi bo'lishi kerak, lekin buning o'rniga boshqa narsa qilinmoqda. To'g'ri amalga oshirish quyidagicha ko'rinadi (this kalit so'zidan foydalanish): public class LocalVariableAndClassMember { private long value; public long calculateValue( final long initial ) { long value = initial; value *= 10; value += this.value; return value; } } Ushbu misol qaysidir ma'noda sodda bo'lsa-da, bu muhim nuqtani ko'rsatadiki, ba'zi hollarda disk raskadrovka va tuzatish uchun bir necha soat vaqt ketishi mumkin.
4. Usul argumentlari va mahalliy o'zgaruvchilar
Tajribasiz Java dasturchilari tez-tez duch keladigan yana bir tuzoq bu usul argumentlarini mahalliy o'zgaruvchilar sifatida ishlatishdir. Java sizga qiymatlarni doimiy bo'lmagan argumentlarga qayta belgilashga imkon beradi (ammo bu asl qiymatga ta'sir qilmaydi): public String sanitize( String str ) { if( !str.isEmpty() ) { str = str.trim(); } str = str.toLowerCase(); return str; } Yuqoridagi kod parchasi oqlangan emas, lekin muammoni ochishda yaxshi ish qiladi: argument str tayinlangan. boshqa qiymat (va asosan mahalliy o'zgaruvchi sifatida ishlatiladi) . Barcha holatlarda (hech qanday istisnosiz) siz ushbu misolsiz ham qilishingiz mumkin va kerak (masalan, argumentlarni doimiy deb e'lon qilish orqali). Masalan: public String sanitize( final String str ) { String sanitized = str; if( !str.isEmpty() ) { sanitized = str.trim(); } sanitized = sanitized.toLowerCase(); return sanitized; } Ushbu oddiy qoidaga rioya qilish orqali, hatto mahalliy o'zgaruvchilarni kiritishda ham berilgan kodni kuzatish va muammoning manbasini topish osonroq bo'ladi.
5. Qadoqlash va ochish
Boxing and unboxing - Java-da ibtidoiy turlarni ( int, long, double va boshqalar ) mos keladigan turdagi o'ramlarga ( Integer, Long, Double va boshqalar) aylantirish uchun ishlatiladigan texnikaning nomi . Jeneriklardan qanday va qachon foydalanish bo'yicha o'quv qo'llanmasining 4-qismida, men ibtidoiy turlarni generiklarning tip parametrlari sifatida o'rash haqida gapirganimda, buni amalda ko'rgansiz. Java kompilyatori avtoboksni amalga oshirish orqali bunday konversiyalarni yashirish uchun qo'lidan kelganicha harakat qilsa ham, ba'zida bu kutilganidan kamroq bo'ladi va kutilmagan natijalar beradi. Keling, misolni ko'rib chiqaylik: public static void calculate( final long value ) { // блок codeа } final Long value = null; calculate( value ); Yuqoridagi kod parchasi yaxshi kompilyatsiya qilinadi. Biroq, u Long va long o'rtasida konvertatsiya qilinadigan qatorga NullPointerExceptionni tashlaydi . Bunday holat bo'yicha maslahat shundan iboratki, ibtidoiy turlardan foydalanish tavsiya etiladi (ammo, bu har doim ham mumkin emasligini allaqachon bilamiz). // блок
6. Interfeyslar
O‘quv qo‘llanmaning 3-qismida “Sinflar va interfeyslarni qanday loyihalash kerak” mavzusida biz interfeyslar va kontrakt dasturlarini muhokama qildik va iloji boricha aniq sinflardan interfeyslarni afzal ko‘rish kerakligini ta’kidladik. Ushbu bo'limning maqsadi sizni hayotiy misollar bilan ko'rsatish orqali interfeyslarni ko'rib chiqishga undashdir. Interfeyslar ma'lum bir dasturga bog'lanmagan (standart usullardan tashqari). Ular faqat shartnomalar bo'lib, misol tariqasida shartnomalarni amalga oshirishda ko'p erkinlik va moslashuvchanlikni ta'minlaydi. Amalga oshirish tashqi tizimlar yoki xizmatlarni o'z ichiga olganida, bu moslashuvchanlik muhimroq bo'ladi. Keling, oddiy interfeys va uni amalga oshirish mumkin bo'lgan misolni ko'rib chiqaylik: public interface TimezoneService { TimeZone getTimeZone( final double lat, final double lon ) throws IOException; } public class TimezoneServiceImpl implements TimezoneService { @Override public TimeZone getTimeZone(final double lat, final double lon) throws IOException { final URL url = new URL( String.format( "http://api.geonames.org/timezone?lat=%.2f&lng=%.2f&username=demo", lat, lon ) ); final HttpURLConnection connection = ( HttpURLConnection )url.openConnection(); connection.setRequestMethod( "GET" ); connection.setConnectTimeout( 1000 ); connection.setReadTimeout( 1000 ); connection.connect(); int status = connection.getResponseCode(); if (status == 200) { // Do something here } return TimeZone.getDefault(); } } Yuqoridagi kod parchasi odatiy interfeys naqshini va uni amalga oshirishni ko'rsatadi. Ushbu dastur ma'lum bir joyning vaqt mintaqasini olish uchun tashqi HTTP xizmatidan ( http://api.geonames.org/ ) foydalanadi. Biroq, chunki shartnoma interfeysga bog'liq bo'lsa, masalan, ma'lumotlar bazasi yoki hatto oddiy tekis fayldan foydalanib, interfeysning boshqa ilovasini joriy qilish juda oson. Ular bilan interfeyslar sinovdan o'tkaziladigan kodni loyihalashda juda foydali. Misol uchun, har bir testda tashqi xizmatlarga qo'ng'iroq qilish har doim ham amaliy emas, shuning uchun uning o'rniga muqobil, eng oddiy dasturni (masalan, stub) amalga oshirish mantiqan to'g'ri keladi: Bu ilova TimezoneService interfeysi talab qilinadigan public class TimezoneServiceTestImpl implements TimezoneService { @Override public TimeZone getTimeZone(final double lat, final double lon) throws IOException { return TimeZone.getDefault(); } } har qanday joyda ishlatilishi mumkin , sinov skriptini tashqi komponentlarga qaramlikdan. Bunday interfeyslardan samarali foydalanishning ko'plab ajoyib misollari Java standart kutubxonasida jamlangan. To'plamlar, ro'yxatlar, to'plamlar - bu interfeyslarda bir nechta ilovalar mavjud bo'lib, ular muammosiz almashtirilishi mumkin va shartnomalar afzalliklarga ega bo'lganda almashtirilishi mumkin. Masalan: public static< T > void print( final Collection< T > collection ) { for( final T element: collection ) { System.out.println( element ); } } print( new HashSet< Object >( /* ... */ ) ); print( new ArrayList< Integer >( /* ... */ ) ); print( new TreeSet< String >( /* ... */ ) );
7. Satrlar
Stringlar Java va boshqa dasturlash tillarida eng koʻp qoʻllaniladigan turlardan biridir. Java tili birlashtirish va taqqoslash operatsiyalarini darhol qo'llab-quvvatlash orqali ko'plab muntazam string manipulyatsiyalarini soddalashtiradi. Bundan tashqari, standart kutubxonada string operatsiyalarini samarali qiladigan ko'plab sinflar mavjud. Aynan shu narsa biz ushbu bo'limda muhokama qilamiz. Java-da satrlar UTF-16 kodlashda ifodalangan o'zgarmas ob'ektlardir. Har safar satrlarni birlashtirganingizda (yoki asl satrni o'zgartiruvchi har qanday operatsiyani bajarganingizda), String sinfining yangi namunasi yaratiladi . Shu sababli, birlashtirish operatsiyasi juda samarasiz bo'lib, String sinfining ko'plab oraliq nusxalarini yaratishga olib kelishi mumkin (umuman, axlat yaratish). Ammo Java standart kutubxonasi ikkita juda foydali sinfni o'z ichiga oladi, ularning maqsadi string manipulyatsiyasini qulay qilishdir. Bular StringBuilder va StringBuffer (ular orasidagi yagona farq shundaki, StringBuffer ip xavfsiz, StringBuilder esa aksincha). Keling, ushbu sinflardan birining ishlatilishiga bir nechta misollarni ko'rib chiqaylik: StringBuilder/StringBuffer final StringBuilder sb = new StringBuilder(); for( int i = 1; i <= 10; ++i ) { sb.append( " " ); sb.append( i ); } sb.deleteCharAt( 0 ); sb.insert( 0, "[" ); sb.replace( sb.length() - 3, sb.length(), "]" ); dan foydalanish satrlarni manipulyatsiya qilishning tavsiya etilgan usuli bo'lsa-da, ikki yoki uchta satrlarni birlashtirishning eng oddiy stsenariysida u ortiqcha ko'rinishi mumkin, shuning uchun oddiy qo'shish operatori ( ("+"), masalan: Birlashtirishni soddalashtirishning eng yaxshi alternativi statik String.format yordamchi usulini taqdim etishda yordam berish uchun qator formatlash hamda Java standart kutubxonasidan foydalanishdir . Bu raqamlar, belgilar, sana/vaqt va hokazolarni o'z ichiga olgan boy format spetsifikatorlarini qo'llab-quvvatlaydi. (To'liq ma'lumot uchun ma'lumotnoma hujjatlariga qarang) String.format usuli har xil ma'lumotlar turlaridan satrlarni yaratish uchun toza va engil yondashuvni ta'minlaydi. Shuni ta'kidlash kerakki, zamonaviy Java IDE'lari String.format usuliga o'tkazilgan argumentlardan format spetsifikatsiyasini tahlil qilishi va mos kelmaslik aniqlansa, ishlab chiquvchilarni ogohlantirishi mumkin. String userId = "user:" + new Random().nextInt( 100 ); String.format( "%04d", 1 ); -> 0001 String.format( "%.2f", 12.324234d ); -> 12.32 String.format( "%tR", new Date() ); -> 21:11 String.format( "%tF", new Date() ); -> 2014-11-11 String.format( "%d%%", 12 ); -> 12%
8. Nomlanish qoidalari
Java - bu ishlab chiquvchilarni nomlash qoidalariga qat'iy rioya qilishga majburlamaydigan til, ammo jamoa Java kodini standart kutubxonada ham, boshqa Java loyihalarida ham izchil ko'rinishini ta'minlaydigan oddiy qoidalar to'plamini ishlab chiqdi:
  • paket nomlari kichik harflarda: org.junit, com.fasterxml.jackson, javax.json
  • sinflar nomlari, ro'yxatlar, interfeyslar, izohlar bosh harf bilan yoziladi: StringBuilder, Runnable, @Override
  • maydonlar yoki usullar nomlari ( statik finaldan tashqari ) tuya yozuvida ko'rsatilgan: isEmpty, format, addAll
  • statik yakuniy maydon yoki sanab o'tish doimiy nomlari bosh harfda, pastki chiziq ("_") bilan ajratilgan: LOG, MIN_RADIX, INSTANCE.
  • mahalliy o'zgaruvchilar yoki usul argumentlari tuya yozuvida yoziladi: str, newLength, minimumCapacity
  • generiklar uchun parametr turi nomlari bosh harfda bitta harf bilan ifodalanadi: T, U, E
Ushbu oddiy konventsiyalarga rioya qilish orqali siz yozgan kod ixcham va uslubi jihatidan boshqa kutubxona yoki ramkadan ajralib turmaydigan ko'rinishga ega bo'ladi va xuddi o'sha odam tomonidan ishlab chiqilgandek bo'ladi (konventsiyalar amalda ishlaydigan kamdan-kam holatlardan biri).
9. Standart kutubxonalar
Qaysi turdagi Java loyihasi ustida ishlayotgan bo'lsangiz ham, Java standart kutubxonalari sizning eng yaxshi do'stlaringizdir. Ha, ularning qo'pol qirralari va g'alati dizayn qarorlari borligiga rozi bo'lish qiyin, ammo 99% hollarda bu mutaxassislar tomonidan yozilgan yuqori sifatli koddir. Buni o'rganishga arziydi. Har bir Java versiyasi mavjud kutubxonalarga ko'plab yangi xususiyatlarni olib keladi (eski xususiyatlar bilan bog'liq ba'zi muammolar bilan) va shuningdek, ko'plab yangi kutubxonalarni qo'shadi. Java 5 java.util.concurrent paketining bir qismi sifatida yangi parallel kutubxona olib keldi . Java 6 (kamroq ma'lum) skriptlarni qo'llab-quvvatlash ( javax.script to'plami) va Java kompilyator API ( javax.tools paketining bir qismi sifatida ) taqdim etdi. Java 7 java.util.concurrent -ga ko'plab yaxshilanishlarni olib keldi, java.nio.file to'plamida yangi I/U kutubxonasini taqdim etdi va java.lang.invoke- dagi dinamik tillarni qo'llab-quvvatladi . Va nihoyat, Java 8 java.time paketiga uzoq kutilgan sana/vaqtni qo'shdi . Java platforma sifatida rivojlanmoqda va uning yuqoridagi o'zgarishlar bilan birga rivojlanishi juda muhim. Har safar loyihangizga uchinchi tomon kutubxonasini yoki ramkasini qo'shishni o'ylab ko'rsangiz, talab qilinadigan funksionallik standart Java kutubxonalarida mavjud emasligiga ishonch hosil qiling (albatta, algoritmlarning ko'plab maxsus va yuqori samarali dasturlari mavjud. standart kutubxonalardagi algoritmlar, lekin ko'p hollarda ular haqiqatan ham kerak emas).
10. O'zgarmaslik
Qo'llanmada va ushbu qismda o'zgarmaslik eslatma sifatida qoladi: iltimos, buni jiddiy qabul qiling. Agar siz yaratgan sinf yoki siz amalga oshiradigan usul o'zgarmaslik kafolatini ta'minlay olsa, u ko'p hollarda bir vaqtning o'zida o'zgartirilishidan qo'rqmasdan hamma joyda ishlatilishi mumkin. Bu sizning dasturchi sifatida hayotingizni (va umid qilamanki, jamoangiz a'zolarining hayotini) osonlashtiradi.
11. Sinov
Test asosida ishlab chiqish amaliyoti (TDD) Java hamjamiyatida juda mashhur bo'lib, kod sifati uchun barni oshiradi. TDD taqdim etayotgan barcha afzalliklarga qaramay, bugungi kunda Java standart kutubxonasi hech qanday test tizimi yoki qo'llab-quvvatlash vositalarini o'z ichiga olmaydi. Biroq, test zamonaviy Java rivojlanishining zaruriy qismiga aylandi va bu bo'limda biz JUnit ramkasidan foydalangan holda bir nechta asosiy usullarni ko'rib chiqamiz . JUnit-da, aslida, har bir test ob'ektning kutilgan holati yoki xatti-harakati haqidagi bayonotlar to'plamidir. Ajoyib testlarni yozish siri ularni oddiy va qisqa qilib, bir vaqtning o'zida bir narsani sinab ko'rishdir. Mashq sifatida String.format string bo'limidan kerakli natijani beradigan funksiya ekanligini tekshirish uchun testlar to'plamini yozamiz . package com.javacodegeeks.advanced.generic; import static org.junit.Assert.assertThat; import static org.hamcrest.CoreMatchers.equalTo; import org.junit.Test; public class StringFormatTestCase { @Test public void testNumberFormattingWithLeadingZeros() { final String formatted = String.format( "%04d", 1 ); assertThat( formatted, equalTo( "0001" ) ); } @Test public void testDoubleFormattingWithTwoDecimalPoints() { final String formatted = String.format( "%.2f", 12.324234d ); assertThat( formatted, equalTo( "12.32" ) ); } } Ikkala test ham juda o'qilishi mumkin va ularning bajarilishi misollardir. Bugungi kunda o'rtacha Java loyihasi yuzlab test holatlarini o'z ichiga oladi, bu esa ishlab chiquvchiga rivojlanish jarayonida regressiyalar yoki xususiyatlar bo'yicha tezkor fikr-mulohazalarni beradi.
12. Keyingi
Qo'llanmaning ushbu qismi Java-da dasturlash amaliyoti va ushbu dasturlash tili uchun qo'llanmalar bilan bog'liq bir qator munozaralarni yakunlaydi. Keyingi safar biz tilning xususiyatlariga qaytamiz, istisnolar, ularning turlari, ulardan qanday va qachon foydalanish haqida Java olamini o'rganamiz.
13. Manba kodini yuklab oling
Bu Advanced Java kursidan umumiy rivojlanish tamoyillari bo'yicha dars edi. Darsning manba kodini bu yerdan yuklab olish mumkin .
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION