JavaRush /Java blogi /Random-UZ /Antipatternlar nima? Keling, misollarni ko'rib chiqaylik ...

Antipatternlar nima? Keling, misollarni ko'rib chiqaylik (1-qism)

Guruhda nashr etilgan
Antipatternlar nima?  Keling, misollarni ko'rib chiqaylik (1-qism) - 1Hammaga xayrli kun! Boshqa kuni men bilan suhbatlashdi va menga antipatternlar haqida savol berishdi: bu qanday hayvon, ularning turlari va amalda misollari. Albatta, men savolga javob berdim, lekin juda yuzaki, chunki men bu masalani o'rganishga juda chuqur kirmaganman. Suhbatdan so'ng men Internetni ko'zdan kechira boshladim va bu mavzuga tobora ko'proq sho'ng'idim. Bugun men eng mashhur antipatternlar va ularning misollarini qisqacha ko'rib chiqmoqchiman, bu sizga ushbu masala bo'yicha kerakli bilimlarni berishi mumkin. Qani boshladik! Shunday qilib, antipattern nima ekanligini muhokama qilishdan oldin, naqsh nima ekanligini eslaylik. Naqsh - bu ilovani loyihalashda yuzaga keladigan umumiy muammolar yoki vaziyatlarni hal qilish uchun takrorlanadigan me'moriy dizayn. Ammo bugun biz ular haqida emas, balki ularning qarama-qarshi tomonlari - antipatternlar haqida gapiramiz. Anti-naqsh - bu samarasiz, xavfli yoki samarasiz bo'lgan tez-tez uchraydigan muammolarni hal qilish uchun umumiy yondashuv. Boshqacha qilib aytganda, bu xato namunasi (ba'zan tuzoq deb ham ataladi). Antipatternlar nima?  Keling, misollarni ko'rib chiqaylik (1-qism) - 2Qoida tariqasida, antipatternlar quyidagi turlarga bo'linadi:
  1. Arxitektura antipatternlari - tizim strukturasini loyihalashda paydo bo'ladigan me'moriy antipatternlar (odatda me'mor tomonidan).
  2. Management Anti Pattern - odatda turli menejerlar (yoki menejerlar guruhlari) duch keladigan boshqaruv sohasidagi antipatternlar.
  3. Development Anti Pattern - antipatternlar oddiy dasturchilar tizimni yozishda paydo bo'ladigan rivojlanish muammolari.
Antipatternlarning ekzotizmi ancha kengroq, ammo biz ularni bugun ko'rib chiqmaymiz, chunki oddiy ishlab chiquvchilar uchun bu juda qiyin bo'ladi. Boshlash uchun menejment sohasidagi antipattern misolini olaylik.

1. Analitik falaj

Tahlil falaji klassik tashkiliy anti-naqsh hisoblanadi. Bu rejalashtirishda vaziyatni ortiqcha tahlil qilishni o'z ichiga oladi, shunda hech qanday qaror yoki harakat amalga oshirilmaydi, bu esa rivojlanishni falaj qiladi. Bu ko'pincha maqsad mukammallikka erishish va tahlil davrini to'liq yakunlash bo'lganda sodir bo'ladi. Ushbu anti-naqsh aylana bo'ylab yurish (yopiq halqa turi), batafsil modellarni qayta ko'rib chiqish va yaratish bilan tavsiflanadi, bu esa o'z navbatida ish jarayoniga xalaqit beradi. Masalan, siz quyidagi narsalarni bashorat qilmoqchisiz: agar foydalanuvchi to'satdan o'z ismining to'rtinchi va beshinchi harflari asosida xodimlar ro'yxatini tuzmoqchi bo'lsa, shu jumladan, ro'yxatda ular ish vaqti orasida eng ko'p ish vaqtini ajratgan loyihalarni yaratmoqchi bo'lsa-chi? Oldingi to'rt yil ichida Yangi yil va sakkizinchi mart? Aslini olganda, bu tahlilning haddan tashqari ko'pligi. Yaxshi real hayot misoli tahlil falaji Kodakni bankrotlikka olib keldi . Mana tahlil falajiga qarshi kurashish uchun bir nechta kichik maslahatlar:
  1. Uzoq muddatli maqsadni qaror qabul qilish uchun mayoq sifatida belgilashingiz kerak, shunda siz qabul qilgan har bir qaror sizni maqsadingizga yaqinlashtiradi va vaqtni belgilashga majburlamaydi.
  2. E'tiboringizni mayda-chuyda narsalarga qaratmang (nega hayotingizdagi so'nggisi bo'lganidek, kichik nuance haqida qaror qabul qilasiz?)
  3. Qaror qabul qilish muddatini belgilang.
  4. Vazifani mukammal bajarishga urinmang: buni juda yaxshi bajarish yaxshiroqdir.
Endi biz juda chuqurlashmaymiz va boshqa boshqaruv antipatternlarini ko'rib chiqamiz. Shuning uchun, preambulasiz, ba'zi me'moriy antipatternlarga o'taylik, chunki, ehtimol, bu maqola menejerlar emas, balki kelajakdagi ishlab chiquvchilar tomonidan o'qiladi.

2. Xudo qarshi

Ilohiy ob'ekt - bu juda ko'p turli xil funktsiyalarning haddan tashqari kontsentratsiyasini tavsiflovchi anti-naqsh, katta hajmdagi turli xil ma'lumotlarni (ilova atrofida aylanadigan ob'ekt) saqlash. Keling, kichik bir misol keltiraylik:
public class SomeUserGodObject {
   private static final String FIND_ALL_USERS_EN = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users;
   private static final String FIND_BY_ID = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users WHERE id = ?";
   private static final String FIND_ALL_CUSTOMERS = "SELECT id, u.email, u.phone, u.first_name_en, u.middle_name_en, u.last_name_en, u.created_date" +
           "  WHERE u.id IN (SELECT up.user_id FROM user_permissions up WHERE up.permission_id = ?)";
   private static final String FIND_BY_EMAIL = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_dateFROM users WHERE email = ?";
   private static final String LIMIT_OFFSET = " LIMIT ? OFFSET ?";
   private static final String ORDER = " ORDER BY ISNULL(last_name_en), last_name_en, ISNULL(first_name_en), first_name_en, ISNULL(last_name_ru), " +
           "last_name_ru, ISNULL(first_name_ru), first_name_ru";
   private static final String CREATE_USER_EN = "INSERT INTO users(id, phone, email, first_name_en, middle_name_en, last_name_en, created_date) " +
           "VALUES (?, ?, ?, ?, ?, ?, ?)";
   private static final String FIND_ID_BY_LANG_CODE = "SELECT id FROM languages WHERE lang_code = ?";
                                  ........
   private final JdbcTemplate jdbcTemplate;
   private Map<String, String> firstName;
   private Map<String, String> middleName;
   private Map<String, String> lastName;
   private List<Long> permission;
                                   ........
   @Override
   public List<User> findAllEnCustomers(Long permissionId) {
       return jdbcTemplate.query( FIND_ALL_CUSTOMERS + ORDER, userRowMapper(), permissionId);
   }
   @Override
   public List<User> findAllEn() {
       return jdbcTemplate.query(FIND_ALL_USERS_EN + ORDER, userRowMapper());
   }
   @Override
   public Optional<List<User>> findAllEnByEmail(String email) {
       var query = FIND_ALL_USERS_EN + FIND_BY_EMAIL + ORDER;
       return Optional.ofNullable(jdbcTemplate.query(query, userRowMapper(), email));
   }
                              .............
   private List<User> findAllWithoutPageEn(Long permissionId, Type type) {
       switch (type) {
           case USERS:
               return findAllEnUsers(permissionId);
           case CUSTOMERS:
               return findAllEnCustomers(permissionId);
           default:
               return findAllEn();
       }
   }
                              ..............private RowMapper<User> userRowMapperEn() {
       return (rs, rowNum) ->
               User.builder()
                       .id(rs.getLong("id"))
                       .email(rs.getString("email"))
                       .accessFailed(rs.getInt("access_counter"))
                       .createdDate(rs.getObject("created_date", LocalDateTime.class))
                       .firstName(rs.getString("first_name_en"))
                       .middleName(rs.getString("middle_name_en"))
                       .lastName(rs.getString("last_name_en"))
                       .phone(rs.getString("phone"))
                       .build();
   }
}
Bu erda biz bir vaqtning o'zida hamma narsani bajaradigan qandaydir katta sinfni ko'ramiz. Ma'lumotlar bazasiga so'rovlarni o'z ichiga oladi, ba'zi ma'lumotlarni o'z ichiga oladi, biz findAllWithoutPageEnbiznes mantig'i bilan fasad usulini ham ko'ramiz. Bunday ilohiy ob'ekt juda katta va qo'llab-quvvatlash uchun noqulay bo'ladi. Biz har bir kod bo'lagida u bilan shug'ullanishimiz kerak: tizimdagi ko'plab tugunlar unga tayanadi va unga mahkam bog'langan. Bunday kodni saqlash tobora qiyinlashib bormoqda. Bunday hollarda uni alohida sinflarga bo'lish kerak, ularning har biri faqat bitta maqsadga (maqsadga) ega bo'ladi. Ushbu misolda siz uni dao sinfiga bo'lishingiz mumkin:
public class UserDaoImpl {
   private static final String FIND_ALL_USERS_EN = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users;
   private static final String FIND_BY_ID = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users WHERE id = ?";

                                   ........
   private final JdbcTemplate jdbcTemplate;

                                   ........
   @Override
   public List<User> findAllEnCustomers(Long permissionId) {
       return jdbcTemplate.query(FIND_ALL_CUSTOMERS + ORDER, userRowMapper(), permissionId);
   }
   @Override
   public List<User> findAllEn() {
       return jdbcTemplate.query(FIND_ALL_USERS_EN + ORDER, userRowMapper());
   }

                               ........
}
Ma'lumotlar va unga kirish usullarini o'z ichiga olgan sinf:
public class UserInfo {
   private Map<String, String> firstName;..
   public Map<String, String> getFirstName() {
       return firstName;
   }
   public void setFirstName(Map<String, String> firstName) {
       this.firstName = firstName;
   }
                    ....
Va biznes mantig'i bilan usulni xizmatga o'tkazish to'g'riroq bo'ladi:
private List<User> findAllWithoutPageEn(Long permissionId, Type type) {
   switch (type) {
       case USERS:
           return findAllEnUsers(permissionId);
       case CUSTOMERS:
           return findAllEnCustomers(permissionId);
       default:
           return findAllEn();
   }
}

3.Singleton

Singleton - bu bitta tarmoqli ilovada ba'zi bir sinfning bitta nusxasi bo'lishini kafolatlaydigan va ushbu ob'ektga global kirish nuqtasini ta'minlaydigan eng oddiy naqsh. Bu haqda ko'proq ma'lumotni shu yerda o'qishingiz mumkin . Lekin bu naqshmi yoki antipatternmi? Antipatternlar nima?  Keling, misollarni ko'rib chiqaylik (1-qism) - 3Keling, ushbu shablonning kamchiliklarini ko'rib chiqaylik:
  1. Global davlat. Biz sinf misoliga kirganda, biz bu sinfning hozirgi holatini yoki uni kim va qachon o'zgartirganini bilmaymiz va bu holat biz kutgandek bo'lmasligi mumkin. Boshqacha qilib aytganda, singleton bilan ishlashning to'g'riligi unga qo'ng'iroqlar tartibiga bog'liq bo'lib, bu quyi tizimlarning bir-biriga bog'liq bo'lishiga olib keladi va natijada rivojlanishning murakkabligini jiddiy ravishda oshiradi.

  2. Singleton SOLID tamoyillaridan birini - Yagona javobgarlik printsipini buzadi - Singleton klassi o'zining bevosita majburiyatlarini bajarishdan tashqari, uning nusxalari sonini ham nazorat qiladi.

  3. Oddiy sinfning singletonga bog'liqligi sinf interfeysida ko'rinmaydi. Odatda singlning namunasi usul parametrlarida o'tkazilmaydi, lekin getInstance()sinfning singletonga bog'liqligini aniqlash uchun to'g'ridan-to'g'ri orqali olinadi, shuning uchun siz har bir usulning amalga oshirilishini chuqur o'rganishingiz kerak - oddiygina ommaviy ko'rish. ob'ektning shartnomasi etarli emas.

    Singletonning mavjudligi umuman dasturning sinovdan o'tish qobiliyatini va xususan, singletondan foydalanadigan sinflarni kamaytiradi. Birinchidan, siz Singleton o'rniga Mock ob'ektini qo'ya olmaysiz, ikkinchidan, agar singleton o'z holatini o'zgartirish uchun interfeysga ega bo'lsa, testlar bir-biriga bog'liq bo'ladi.

    Boshqacha qilib aytganda, singleton ulanishni oshiradi va yuqorida aytilganlarning barchasi ulanishning kuchayishi natijasidan boshqa narsa emas.

    Va agar siz bu haqda o'ylab ko'rsangiz, singletondan foydalanishdan qochish mumkin. Masalan, ob'ektning nusxalari sonini nazorat qilish uchun har xil turdagi zavodlardan foydalanish juda mumkin (va zarur).

    Eng katta xavf - bu butun dastur arxitekturasini singletonlar asosida qurishga urinishda. Ushbu yondashuv uchun juda ko'p ajoyib alternativalar mavjud. Eng muhim misol - Bahor, ya'ni uning IoC konteynerlari: u erda xizmatlarni yaratishni nazorat qilish muammosi tabiiy ravishda hal qilinadi, chunki ular aslida "steroidlar zavodlari".

    Endi bu mavzu bo'yicha juda ko'p holivar bor, shuning uchun singlning naqsh yoki antipattern ekanligini siz hal qilishingiz kerak.

    Va biz bu haqda to'xtalmaymiz va bugungi kunning so'nggi dizayn namunasiga o'tamiz - poltergeist.

4. Poltergeist

Poltergeist - bu foydali bo'lmagan sinf antipattern bo'lib, u boshqa sinf usullarini chaqirish uchun ishlatiladi yoki shunchaki keraksiz abstraktsiya qatlamini qo'shadi. Antipattern davlatdan mahrum bo'lgan qisqa muddatli ob'ektlar shaklida o'zini namoyon qiladi. Ushbu ob'ektlar ko'pincha boshqa, bardoshli ob'ektlarni ishga tushirish uchun ishlatiladi.
public class UserManager {
   private UserService service;
   public UserManager(UserService userService) {
       service = userService;
   }
   User createUser(User user) {
       return service.create(user);
   }
   Long findAllUsers(){
       return service.findAll().size();
   }
   String findEmailById(Long id) {
       return service.findById(id).getEmail();}
   User findUserByEmail(String email) {
       return service.findByEmail(email);
   }
   User deleteUserById(Long id) {
       return service.delete(id);
   }
}
Bizga shunchaki vositachi bo'lgan va o'z ishini boshqa birovga topshiradigan ob'ekt nima uchun kerak? Biz uni o'chirib tashlaymiz va u amalga oshiradigan kichik funksiyalarni uzoq muddatli ob'ektlarga o'tkazamiz. Keyinchalik, bizni (oddiy ishlab chiquvchilar sifatida) eng katta qiziqish uyg'otadigan naqshlarga o'tamiz - developing antipatterns .

5. Qattiq kod

Shunday qilib, biz bu dahshatli so'zga - qattiq kodga keldik. Ushbu antipatternning mohiyati shundaki, kod ma'lum bir apparat konfiguratsiyasi va/yoki tizim muhiti bilan mustahkam bog'langan, bu esa uni boshqa konfiguratsiyalarga o'tkazishni juda qiyinlashtiradi. Ushbu antipattern sehrli raqamlar bilan chambarchas bog'liq (ular ko'pincha bir-biriga bog'langan). Misol:
public Connection buildConnection() throws Exception {
   Class.forName("com.mysql.cj.jdbc.Driver");
   connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/someDb?characterEncoding=UTF-8&characterSetResults=UTF-8&serverTimezone=UTC", "user01", "12345qwert");
   return connection;
}
Tirnoqlangan, shunday emasmi? Bu erda biz to'g'ridan-to'g'ri ulanish konfiguratsiyasini o'rnatamiz, natijada kod faqat MySQL bilan to'g'ri ishlaydi va ma'lumotlar bazasini o'zgartirish uchun siz kodga kirishingiz va hamma narsani qo'lda o'zgartirishingiz kerak bo'ladi. Konfiguratsiyalarni alohida faylga qo'yish yaxshi yechim bo'ladi:
spring:
  datasource:
    jdbc-url:jdbc:mysql://localhost:3306/someDb?characterEncoding=UTF-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username:  user01
    password:  12345qwert
Yana bir variant - uni doimiylarga o'tkazish.

6. Qayiq langari

Antipatternlar kontekstidagi qayiq langari, ba'zi optimallashtirish yoki qayta ishlashdan keyin qolgan tizimning foydalanilmagan qismlarini saqlashni anglatadi. Bundan tashqari, kodning ba'zi qismlari, agar siz ularni qayta ishlatishingiz kerak bo'lsa, "kelajak uchun" qoldirilishi mumkin. Bu aslida kodni axlat qutisiga aylantiradi. Antipatternlar nima?  Keling, misollarni ko'rib chiqaylik (1-qism) - 4Misol:
public User update(Long id, User request) {
   User user = mergeUser(findById(id), request);
   return userDAO.update(user);
}
private User mergeUser(User findUser, User requestUser) {
   return new User(
           findUser.getId(),
           requestUser.getEmail() != null ? requestUser.getEmail() : findUser.getEmail(),
           requestUser.getFirstName() != null ? requestUser.getFirstName() : findUser.getFirstNameRu(),
           requestUser.getMiddleName() != null ? requestUser.getMiddleName() : findUser.getMiddleNameRu(),
           requestUser.getLastName() != null ? requestUser.getLastName() : findUser.getLastNameEn(),
           requestUser.getPhone() != null ? requestUser.getPhone() : findUser.getPhone());
}
Bizda ma'lumotlar bazasidan foydalanuvchi va yangilash uchun kelgan ma'lumotlarini birlashtirish uchun alohida usuldan foydalanadigan yangilash usuli mavjud (agar yangilash uchun kelgan odamda bo'sh maydon bo'lsa, u eski deb yoziladi. ma'lumotlar bazasidan). Masalan, yozuvlarni eskilari bilan birlashtirmaslik kerak, lekin bo'sh maydonlar bo'lsa ham, ustiga yozish kerak edi:
public User update(Long id, User request) {
   return userDAO.update(user);
}
Natijada, mergeUseru endi ishlatilmaydi va uni o'chirish juda achinarli: agar u (yoki uning g'oyasi) hali ham foydali bo'lsa-chi? Bunday kod faqat tizimlarni murakkablashtiradi va chalkashtirib yuboradi, aslida hech qanday amaliy ahamiyatga ega emas. Shuni unutmasligimiz kerakki, "o'lik qismlar" bo'lgan bunday kodni boshqa loyihaga ketganingizda hamkasbingizga o'tkazish qiyin bo'ladi. Qayiq langarlari bilan ishlashning eng yaxshi usuli - bu kodni qayta tiklash, ya'ni kodning ushbu bo'limlarini o'chirish (afsuski, afsuski). Shuningdek, rivojlanishni rejalashtirishda siz bunday langarlarning paydo bo'lishini hisobga olishingiz kerak (quyruqlarni tozalash uchun vaqt ajrating).

7.Ob'ekt axlatxonasi

Ushbu antipatternni tasvirlash uchun avvalo ob'ekt bilan tanishishingiz kerak hovuz naqsh . Ob'ektlar hovuzi (resurslar hovuzi) generativ dizayn naqshidir , ishga tushirilgan va foydalanishga tayyor ob'ektlar to'plami. Ilova ob'ektni talab qilganda, u yangidan yaratilmaydi, balki shu hovuzdan olinadi. Ob'ekt endi kerak bo'lmaganda, u yo'q qilinmaydi, balki hovuzga qaytariladi. Odatda har safar yaratish uchun resurs talab qiladigan og'ir ob'ektlar uchun ishlatiladi, masalan, ma'lumotlar bazasi ulanishi. Keling, misol uchun kichik va oddiy misolni ko'rib chiqaylik. Shunday qilib, bizda ushbu naqshni ifodalovchi sinf mavjud:
class ReusablePool {
   private static ReusablePool pool;
   private List<Resource> list = new LinkedList<>();
   private ReusablePool() {
       for (int i = 0; i < 3; i++)
           list.add(new Resource());
   }
   public static ReusablePool getInstance() {
       if (pool == null) {
           pool = new ReusablePool();
       }
       return pool;
   }
   public Resource acquireResource() {
       if (list.size() == 0) {
           return new Resource();
       } else {
           Resource r = list.get(0);
           list.remove(r);
           return r;
       }
   }
   public void releaseResource(Resource r) {
       list.add(r);
   }
}
Biz bu sinfni yuqorida tavsiflangan singleton naqsh/antipattern shaklida taqdim etamiz , ya'ni bu turdagi faqat bitta ob'ekt bo'lishi mumkin, u ma'lum ob'ektlarda ishlaydi Resource, konstruktorda sukut bo'yicha hovuz 4 nusxa bilan to'ldiriladi; bunday ob'ekt olinganda, u hovuzdan chiqariladi (agar u yo'q bo'lsa, u yaratiladi va darhol beriladi) va oxirida ob'ektni qaytarib qo'yish usuli mavjud. Ob'ektlar Resourcequyidagicha ko'rinadi:
public class Resource {
   private Map<String, String> patterns;
   public Resource() {
       patterns = new HashMap<>();
       patterns.put("заместитель", "https://studfile.net/preview/3676297/page:3/");
       patterns.put("мост", "https://studfile.net/preview/3676297/page:4/");
       patterns.put("фасад", "https://studfile.net/preview/3676297/page:5/");
       patterns.put("строитель", "https://studfile.net/preview/3676297/page:6/#16");
   }
   public Map<String, String> getPatterns() {
       return patterns;
   }
   public void setPatterns(Map<String, String> patterns) {
       this.patterns = patterns;
   }
}
Bu erda bizda kalit sifatida naqshlarning nomlari va qiymat sifatida ularga havolalar, shuningdek xaritaga kirish usullari bilan xaritani o'z ichiga olgan kichik ob'ekt mavjud. Keling, ko'rib chiqaylik main:
class SomeMain {
   public static void main(String[] args) {
       ReusablePool pool = ReusablePool.getInstance();

       Resource firstResource = pool.acquireResource();
       Map<String, String> firstPatterns = firstResource.getPatterns();
       // ......Howим-то образом используем нашу мапу.....
       pool.releaseResource(firstResource);

       Resource secondResource = pool.acquireResource();
       Map<String, String> secondPatterns = firstResource.getPatterns();
       // ......Howим-то образом используем нашу мапу.....
       pool.releaseResource(secondResource);

       Resource thirdResource = pool.acquireResource();
       Map<String, String> thirdPatterns = firstResource.getPatterns();
       // ......Howим-то образом используем нашу мапу.....
       pool.releaseResource(thirdResource);
   }
}
Bu erda hamma narsa aniq: biz hovuz ob'ektini olamiz, undan resurslari bo'lgan ob'ektni chiqaramiz, undan xarita olamiz, u bilan biror narsa qilamiz va keyin qayta foydalanish uchun hammasini hovuzga qaytaramiz. Voila: bu yerda sizda ob'ekt hovuzi naqsh mavjud. Ammo biz antipatternlar haqida gapirgan edik, shunday emasmi? Keling, ushbu ishni ko'rib chiqaylik main:
Resource fourthResource = pool.acquireResource();
   Map<String, String> fourthPatterns = firstResource.getPatterns();
// ......Howим-то образом используем нашу мапу.....
fourthPatterns.clear();
firstPatterns.put("first","blablabla");
firstPatterns.put("second","blablabla");
firstPatterns.put("third","blablabla");
firstPatterns.put("fourth","blablabla");
pool.releaseResource(fourthResource);
Bu erda yana resurs ob'ekti olinadi, uning naqshlari bilan xaritasi olinadi va u bilan nimadir bajariladi, lekin ob'ektlar hovuziga qaytishdan oldin xarita tozalanadi va tushunarsiz ma'lumotlar bilan to'ldiriladi, bu esa ushbu Resurs ob'ektini qayta ishlatish uchun yaroqsiz qiladi. Ob'ekt pulining asosiy nuanslaridan biri shundaki, ob'ekt qaytarilgandan so'ng uni keyingi qayta foydalanish uchun mos holatga qaytarish kerak. Agar ob'ektlar hovuzga qaytarilgandan so'ng noto'g'ri yoki aniqlanmagan holatda bo'lsa, bu konstruktsiya ob'ektning chuqurligi deb ataladi. Qayta foydalanish mumkin bo'lmagan narsalarni saqlashdan nima foyda? Bunday holda siz konstruktorda ichki xaritani o'zgarmas qilishingiz mumkin:
public Resource() {
   patterns = new HashMap<>();
   patterns.put("заместитель", "https://studfile.net/preview/3676297/page:3/");
   patterns.put("мост", "https://studfile.net/preview/3676297/page:4/");
   patterns.put("фасад", "https://studfile.net/preview/3676297/page:5/");
   patterns.put("строитель", "https://studfile.net/preview/3676297/page:6/#16");
   patterns = Collections.unmodifiableMap(patterns);
}
(tarkibni o'zgartirishga urinishlar va istaklar UnsupportedOperationException bilan birga tushadi). Antipatternlar - bu ishlab chiquvchilar ko'pincha vaqt etishmasligi, e'tiborsizlik, tajribasizlik yoki menejerlarning zarbalari tufayli tushadigan tuzoqlardir. Vaqtning odatiy etishmasligi va shoshqaloqlik kelajakda dastur uchun katta muammolarga olib kelishi mumkin, shuning uchun bu xatolarni oldindan bilish va oldini olish kerak. Antipatternlar nima?  Keling, misollarni ko'rib chiqaylik (1-qism) - 6Shu bilan maqolaning birinchi qismi nihoyasiga yetdi: davom etish .
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION