CodeGym/Java Blog/Random/Ano ang mga anti-pattern? Tingnan natin ang ilang halimba...
John Squirrels
Antas
San Francisco

Ano ang mga anti-pattern? Tingnan natin ang ilang halimbawa (Bahagi 1)

Nai-publish sa grupo
Magandang araw sa lahat! Noong isang araw, nagkaroon ako ng panayam sa trabaho, at tinanong ako ng ilang mga katanungan tungkol sa mga anti-pattern: kung ano ang mga ito, anong mga uri ang mayroon, at kung anong mga praktikal na halimbawa ang mayroon. Siyempre, sinagot ko ang tanong, ngunit napakababaw, dahil hindi pa ako sumabak sa paksang ito. Pagkatapos ng pakikipanayam, nagsimula akong magsaliksik sa Internet at mas lalo kong isinawsaw ang aking sarili sa paksa. Ano ang mga anti-pattern?  Tingnan natin ang ilang halimbawa (Bahagi 1) - 1 Ngayon gusto kong magbigay ng maikling pangkalahatang-ideya ng mga pinakasikat na anti-pattern at suriin ang ilang mga halimbawa. Umaasa ako na ang pagbabasa nito ay magbibigay sa iyo ng kaalaman na kailangan mo sa lugar na ito. Magsimula na tayo! Bago natin talakayin kung ano ang anti-pattern, alalahanin natin kung ano ang pattern ng disenyo. Isang pattern ng disenyoay isang paulit-ulit na solusyon sa arkitektura para sa mga karaniwang problema o sitwasyon na lumitaw kapag nagdidisenyo ng isang aplikasyon. Ngunit ngayon hindi namin pinag-uusapan ang tungkol sa kanila, ngunit sa halip ang kanilang mga kabaligtaran - mga anti-pattern. Ang isang anti-pattern ay isang laganap ngunit hindi epektibo, peligroso, at/o hindi produktibong diskarte sa paglutas ng isang klase ng mga karaniwang problema. Sa madaling salita, ito ay isang pattern ng mga pagkakamali (tinatawag ding bitag). Bilang isang patakaran, ang mga anti-pattern ay nahahati sa mga sumusunod na uri:
  1. Mga anti-pattern ng arkitektura — Ang mga anti-pattern na ito ay lumitaw habang ang istraktura ng isang sistema ay idinisenyo (karaniwan ay ng isang arkitekto).
  2. Mga anti-pattern ng pamamahala/organisasyon — Ito ay mga anti-pattern sa pamamahala ng proyekto, kadalasang nakakaharap ng iba't ibang mga tagapamahala (o mga grupo ng mga tagapamahala).
  3. Development anti-patterns — Ang mga anti-pattern na ito ay lumitaw habang ang isang sistema ay ipinatupad ng mga ordinaryong programmer.
Ang buong hanay ng mga anti-pattern ay higit na kakaiba, ngunit hindi namin isasaalang-alang ang lahat ng ito ngayon. Para sa mga ordinaryong developer, iyon ay magiging labis. Para sa panimula, isaalang-alang natin ang isang anti-pattern ng pamamahala bilang isang halimbawa.

1. Analytical paralysis

Paralisis ng pagsusuriay itinuturing na isang klasikong anti-pattern ng pamamahala. Ito ay nagsasangkot ng labis na pagsusuri sa sitwasyon sa panahon ng pagpaplano, nang sa gayon ay walang desisyon o aksyon na ginawa, mahalagang paralisado ang proseso ng pag-unlad. Madalas itong nangyayari kapag ang layunin ay makamit ang pagiging perpekto at ganap na isaalang-alang ang lahat sa panahon ng pagsusuri. Ang anti-pattern na ito ay nailalarawan sa pamamagitan ng paglalakad nang paikot-ikot (isang run-of-the-mill closed loop), pagrerebisa at paglikha ng mga detalyadong modelo, na nakakasagabal naman sa daloy ng trabaho. Halimbawa, sinusubukan mong hulaan ang mga bagay sa isang antas: ngunit paano kung biglang gustong gumawa ng isang user ng listahan ng mga empleyado batay sa ikaapat at ikalimang titik ng kanilang pangalan, kasama ang listahan ng mga proyekto kung saan sila gumugol ng pinakamaraming oras ng pagtatrabaho sa pagitan ng Bagong Taon at Pandaigdigang Araw ng Kababaihan sa nakalipas na apat na taon? Sa esensya, ito' s sobrang pagsusuri. Narito ang ilang mga tip para labanan ang paralisis ng pagsusuri:
  1. Kailangan mong tukuyin ang isang pangmatagalang layunin bilang isang beacon para sa paggawa ng desisyon, upang ang bawat isa sa iyong mga desisyon ay maglalapit sa iyo sa layunin sa halip na maging sanhi ng iyong pagtigil.
  2. Huwag tumutok sa mga bagay na walang kabuluhan (bakit gagawa ng desisyon tungkol sa isang hindi gaanong mahalagang detalye na parang ito ang pinakamahalagang desisyon sa iyong buhay?)
  3. Magtakda ng deadline para sa isang desisyon.
  4. Huwag subukang kumpletuhin ang isang gawain nang perpekto — mas mabuting gawin ito nang napakahusay.
Hindi na kailangang masyadong malalim dito, kaya hindi namin isasaalang-alang ang iba pang managerial na anti-pattern. Samakatuwid, nang walang anumang pagpapakilala, lilipat kami sa ilang mga anti-pattern ng arkitektura, dahil ang artikulong ito ay malamang na mababasa ng mga developer sa hinaharap kaysa sa mga tagapamahala.

2. Tutol ang Diyos

Ang object ng Diyos ay isang anti-pattern na naglalarawan ng labis na konsentrasyon ng lahat ng uri ng mga function at malaking halaga ng magkakaibang data (isang bagay na umiikot sa paligid ng application). Kumuha ng isang maliit na halimbawa:
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();
   }
}
Dito nakikita natin ang isang malaking klase na gumagawa ng lahat. Naglalaman ito ng mga query sa database pati na rin ang ilang data. Nakikita rin namin ang findAllWithoutPageEn facade method, na kinabibilangan ng business logic. Ang gayong bagay ng Diyos ay nagiging napakalaki at mahirap na mapanatili nang maayos. Kailangan nating guluhin ito sa bawat piraso ng code. Maraming mga bahagi ng system ang umaasa dito at mahigpit na pinagsama dito. Ito ay nagiging mas mahirap at mas mahirap upang mapanatili ang naturang code. Sa ganitong mga kaso, ang code ay dapat na hatiin sa magkakahiwalay na mga klase, na ang bawat isa ay magkakaroon lamang ng isang layunin. Sa halimbawang ito, maaari nating hatiin ang object ng Diyos sa isang klase ng Dao:
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());
   }

                               ........
}
Isang klase na naglalaman ng data at mga pamamaraan para sa pag-access ng data:
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;
   }
                    ....
At magiging mas angkop na ilipat ang pamamaraan na may lohika ng negosyo sa isang serbisyo:
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

Ang singleton ay ang pinakasimpleng pattern. Tinitiyak nito na sa isang single-threaded na application ay magkakaroon ng isang instance ng isang klase, at nagbibigay ito ng pandaigdigang access point sa object na ito. Ngunit ito ba ay isang pattern o isang anti-pattern? Tingnan natin ang mga disadvantages ng pattern na ito:
  1. Global state Kapag na-access natin ang instance ng klase, hindi natin alam ang kasalukuyang estado ng klase na ito. Hindi namin alam kung sino ang nagbago nito o kung kailan. Ang estado ay maaaring hindi katulad ng inaasahan natin. Sa madaling salita, ang kawastuhan ng pagtatrabaho sa isang singleton ay nakasalalay sa pagkakasunud-sunod ng mga pag-access dito. Nangangahulugan ito na ang mga subsystem ay nakadepende sa isa't isa at, bilang resulta, ang isang disenyo ay nagiging seryosong mas kumplikado.

  2. Ang singleton ay lumalabag sa SOLID na prinsipyo — ang nag-iisang responsibilidad na prinsipyo: bilang karagdagan sa mga direktang tungkulin nito, kinokontrol din ng singleton class ang bilang ng mga pagkakataon.

  3. Ang pagdepende ng isang ordinaryong klase sa isang singleton ay hindi makikita sa interface ng klase. Dahil ang isang singleton instance ay hindi karaniwang ipinapasa bilang isang argumento ng pamamaraan, ngunit sa halip ay nakuha nang direkta sa pamamagitan ng getInstance(), kailangan mong pumasok sa pagpapatupad ng bawat pamamaraan upang matukoy ang pag-asa ng klase sa singleton — tumitingin lamang sa publiko ng isang klase hindi sapat ang kontrata.

    Ang pagkakaroon ng singleton ay binabawasan ang testability ng application sa kabuuan at ang mga klase na gumagamit ng singleton sa partikular. Una sa lahat, hindi mo maaaring palitan ang singleton ng mock object. Pangalawa, kung ang isang singleton ay may interface para sa pagbabago ng estado nito, ang mga pagsubok ay depende sa isa't isa.

    Sa madaling salita, ang isang singleton ay nagdaragdag ng pagkabit, at lahat ng nabanggit sa itaas ay hindi hihigit sa isang resulta ng pagtaas ng pagkabit.

    At kung iisipin mo, maiiwasan mong gumamit ng singleton. Halimbawa, ito ay lubos na posible (at talagang kinakailangan) na gumamit ng iba't ibang uri ng mga pabrika upang makontrol ang bilang ng mga pagkakataon ng isang bagay.

    Ang pinakamalaking panganib ay nasa pagtatangkang bumuo ng isang buong arkitektura ng application batay sa mga singleton. Mayroong maraming mga kahanga-hangang alternatibo sa diskarteng ito. Ang pinakamahalagang halimbawa ay ang Spring, lalo na ang mga lalagyan ng IoC: natural na solusyon ang mga ito sa problema ng pagkontrol sa paglikha ng mga serbisyo, dahil ang mga ito ay talagang "mga pabrika ng mga steroid".

    Maraming mga walang-hanggan at hindi mapagkakasunduang mga debate ang nagngangalit ngayon sa paksang ito. Nasa sa iyo na magpasya kung ang isang singleton ay isang pattern o anti-pattern.

    Hindi kami magtatagal dito. Sa halip, magpapatuloy tayo sa huling pattern ng disenyo para sa araw na ito — poltergeist.

4. Poltergeist

Ang poltergeist ay isang anti-pattern na kinasasangkutan ng isang walang kabuluhang klase na ginagamit upang tawagan ang mga pamamaraan ng isa pang klase o nagdaragdag lamang ng hindi kinakailangang layer ng abstraction. Ang anti-pattern na ito ay nagpapakita ng sarili bilang mga panandaliang bagay, na walang estado. Ang mga bagay na ito ay kadalasang ginagamit upang simulan ang iba, mas permanenteng mga bagay.
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);
   }
}
Bakit kailangan natin ng isang bagay na isang tagapamagitan lamang at ipinagkatiwala ang gawain nito sa ibang tao? Inalis namin ito at inililipat ang maliit na pag-andar na mayroon ito sa mga pangmatagalang bagay. Susunod, lumipat kami sa mga pattern na pinaka-interesado sa amin (bilang mga ordinaryong developer), ibig sabihin, mga anti-pattern ng pagbuo .

5. Hard coding

Kaya nakarating na kami sa kakila-kilabot na salitang ito: hard coding. Ang esensya ng anti-pattern na ito ay ang code ay mahigpit na nakatali sa isang partikular na configuration ng hardware at/o system environment. Ito ay lubos na nagpapalubha sa pag-port ng code sa iba pang mga pagsasaayos. Ang anti-pattern na ito ay malapit na nauugnay sa mga magic number (ang mga anti-pattern na ito ay madalas na magkakaugnay). Halimbawa:
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;
}
Masakit, hindi ba? Dito namin hard code ang aming mga setting ng koneksyon. Bilang resulta, ang code ay gagana lamang ng tama sa MySQL. Upang baguhin ang database, kakailanganin naming sumisid sa code at baguhin ang lahat nang manu-mano. Ang isang magandang solusyon ay ang ilagay ang pagsasaayos sa isang hiwalay na file:
spring:
  datasource:
    jdbc-url:jdbc:mysql://localhost:3306/someDb?characterEncoding=UTF-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username:  user01
    password:  12345qwert
Ang isa pang pagpipilian ay ang paggamit ng mga constants.

6. Bangka anchor

Sa konteksto ng mga anti-pattern, nangangahulugan ang isang boat anchor na panatilihin ang mga bahagi ng system na hindi na ginagamit pagkatapos magsagawa ng ilang pag-optimize o refactoring. Gayundin, ang ilang bahagi ng code ay maaaring panatilihing "para magamit sa hinaharap" kung sakaling bigla mong kailanganin ang mga ito. Sa pangkalahatan, ginagawa nitong dustbin ang iyong code. Halimbawa:
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());
}
Mayroon kaming isang paraan ng pag-update na gumagamit ng isang hiwalay na paraan upang pagsamahin ang data ng gumagamit mula sa database sa data ng gumagamit na ipinasa sa pamamaraan (kung ang gumagamit ay pumasa sa paraan ng pag-update ay may null na field, kung gayon ang lumang halaga ng field ay kinuha mula sa database) . Kung gayon, ipagpalagay na mayroong isang bagong kinakailangan na ang mga talaan ay hindi dapat isama sa mga luma, ngunit sa halip, kahit na mayroong mga null na patlang, ginagamit ang mga ito upang i-overwrite ang mga luma:
public User update(Long id, User request) {
   return userDAO.update(user);
}
Nangangahulugan ito na hindi na ginagamit ang mergeUser, ngunit nakakalungkot na tanggalin ito — paano kung ang pamamaraang ito (o ang ideya ng pamamaraang ito) ay maaaring magamit balang araw? Ang ganitong code ay nagpapalubha lamang sa mga system at nagpapakilala ng kalituhan, na halos walang praktikal na halaga. Hindi natin dapat kalimutan na ang naturang code na may "mga patay na piraso" ay magiging mahirap na ipasa sa isang kasamahan kapag umalis ka para sa isa pang proyekto. Ang pinakamahusay na paraan upang makitungo sa mga anchor ng bangka ay ang refactor ang code, ibig sabihin, tanggalin ang mga seksyon ng code (nakakasakit ng damdamin, alam ko). Bilang karagdagan, kapag inihahanda ang iskedyul ng pag-unlad, kinakailangang isaalang-alang ang mga naturang anchor (upang maglaan ng oras para sa pag-aayos).

7. Bagay na cesspool

Upang ilarawan ang anti-pattern na ito, kailangan mo munang pamilyar sa pattern ng object pool . Ang object pool (resource pool) ay isang creational design pattern , isang set ng mga nasimulan at handa nang gamitin na mga bagay. Kapag ang isang application ay nangangailangan ng isang bagay, ito ay kinuha mula sa pool na ito sa halip na muling likhain. Kapag hindi na kailangan ang isang bagay, hindi ito nasisira. Sa halip, ibinalik ito sa pool. Karaniwang ginagamit ang pattern na ito para sa mga mabibigat na bagay na nakakaubos ng oras upang gawin sa tuwing kailangan ang mga ito, tulad ng kapag kumokonekta sa isang database. Tingnan natin ang isang maliit at simpleng halimbawa. Narito ang isang klase na kumakatawan sa pattern na ito:
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);
   }
}
Ang klase na ito ay ipinakita sa anyo ng singleton pattern/anti-pattern sa itaas, ibig sabihin, maaari lamang magkaroon ng isang bagay ng ganitong uri. Gumagamit ito ng ilang Resourcemga bagay. Bilang default, pinupuno ng constructor ang pool ng 4 na pagkakataon. Kapag nakakuha ka ng isang bagay, ito ay tinanggal mula sa pool (kung walang magagamit na bagay, ang isa ay nilikha at agad na ibinalik). At sa dulo, mayroon tayong paraan upang maibalik ang bagay. Ang mga bagay na mapagkukunan ay ganito ang hitsura:
public class Resource {
   private Map<String, String> patterns;
   public Resource() {
       patterns = new HashMap<>();
       patterns.put("proxy", "https://en.wikipedia.org/wiki/Proxy_pattern");
       patterns.put("bridge", "https://en.wikipedia.org/wiki/Bridge_pattern");
       patterns.put("facade", "https://en.wikipedia.org/wiki/Facade_pattern");
       patterns.put("builder", "https://en.wikipedia.org/wiki/Builder_pattern");
   }
   public Map<String, String> getPatterns() {
       return patterns;
   }
   public void setPatterns(Map<String, String> patterns) {
       this.patterns = patterns;
   }
}
Narito mayroon kaming isang maliit na bagay na naglalaman ng isang mapa na may mga pangalan ng pattern ng disenyo bilang susi at kaukulang mga link sa Wikipedia bilang halaga, pati na rin ang mga paraan upang ma-access ang mapa. Tingnan natin ang pangunahing:
class SomeMain {
   public static void main(String[] args) {
       ReusablePool pool = ReusablePool.getInstance();

       Resource firstResource = pool.acquireResource();
       Map<String, String> firstPatterns = firstResource.getPatterns();
       // use our map somehow...
       pool.releaseResource(firstResource);

       Resource secondResource = pool.acquireResource();
       Map<String, String> secondPatterns = firstResource.getPatterns();
       // use our map somehow...
       pool.releaseResource(secondResource);

       Resource thirdResource = pool.acquireResource();
       Map<String, String> thirdPatterns = firstResource.getPatterns();
       // use our map somehow...
       pool.releaseResource(thirdResource);
   }
}
Ang lahat dito ay sapat na malinaw: nakakakuha tayo ng pool object, kumuha ng object na may resources mula sa pool, kumuha ng mapa mula sa Resource object, gumawa ng isang bagay dito, at ilagay ang lahat ng ito sa lugar nito sa pool para sa karagdagang paggamit. Voila, ito ang pattern ng disenyo ng object pool. Ngunit pinag-uusapan natin ang tungkol sa mga anti-pattern, tama ba? Isaalang-alang natin ang sumusunod na kaso sa pangunahing pamamaraan:
Resource fourthResource = pool.acquireResource();
   Map<String, String> fourthPatterns = firstResource.getPatterns();
// use our map somehow...
fourthPatterns.clear();
firstPatterns.put("first","blablabla");
firstPatterns.put("second","blablabla");
firstPatterns.put("third","blablabla");
firstPatterns.put("fourth","blablabla");
pool.releaseResource(fourthResource);
Dito, muli, nakakakuha tayo ng Resource object, nakukuha natin ang mapa ng mga pattern nito, at may ginagawa tayo sa mapa. Ngunit bago i-save ang mapa pabalik sa pool ng mga bagay, ito ay iki-clear at pagkatapos ay mapupunan ng sirang data, na ginagawang ang Resource object ay hindi angkop para sa muling paggamit. Ang isa sa mga pangunahing detalye ng isang object pool ay na kapag ang isang bagay ay ibinalik, dapat itong ibalik sa isang estado na angkop para sa karagdagang muling paggamit. Kung ang mga bagay na ibinalik sa pool ay mananatili sa isang hindi tama o hindi natukoy na estado, kung gayon ang aming disenyo ay tinatawag na isang object cesspool. May katuturan bang mag-imbak ng mga bagay na hindi angkop para sa muling paggamit? Sa sitwasyong ito, maaari nating gawing hindi nababago ang panloob na mapa sa constructor:
public Resource() {
   patterns = new HashMap<>();
   patterns.put("proxy", "https://en.wikipedia.org/wiki/Proxy_pattern");
   patterns.put("bridge", "https://en.wikipedia.org/wiki/Bridge_pattern");
   patterns.put("facade", "https://en.wikipedia.org/wiki/Facade_pattern");
   patterns.put("builder", "https://en.wikipedia.org/wiki/Builder_pattern");
   patterns = Collections.unmodifiableMap(patterns);
}
Ang mga pagtatangka at ang pagnanais na baguhin ang mga nilalaman ng mapa ay maglalaho salamat sa UnsupportedOperationException na kanilang bubuo. Ang mga anti-pattern ay mga bitag na madalas na nakakaharap ng mga developer dahil sa matinding kakulangan ng oras, kawalang-ingat, kawalan ng karanasan, o pressure mula sa mga tagapamahala ng proyekto. Ang pagmamadali, na karaniwan, ay maaaring humantong sa malalaking problema para sa aplikasyon sa hinaharap, kaya kailangan mong malaman ang tungkol sa mga error na ito at maiwasan ang mga ito nang maaga. Ito ang nagtatapos sa unang bahagi ng artikulo. Itutuloy...
Mga komento
  • Sikat
  • Bago
  • Luma
Dapat kang naka-sign in upang mag-iwan ng komento
Wala pang komento ang page na ito