8. গোল্ডেন হাতুড়ি
একটি সুবর্ণ হাতুড়ি হল একটি বিরোধী প্যাটার্ন যা আত্মবিশ্বাস দ্বারা সংজ্ঞায়িত করা হয় যে একটি নির্দিষ্ট সমাধান সর্বজনীনভাবে প্রযোজ্য। উদাহরণ:-
একটি সমস্যার সম্মুখীন হওয়ার পরে এবং নিখুঁত সমাধানের জন্য একটি প্যাটার্ন খুঁজে পাওয়ার পরে, একজন প্রোগ্রামার নির্দিষ্ট ক্ষেত্রে উপযুক্ত সমাধান খোঁজার পরিবর্তে বর্তমান এবং ভবিষ্যতের সমস্ত প্রকল্পে এটি প্রয়োগ করে সর্বত্র এই প্যাটার্নটি আটকে রাখার চেষ্টা করেন।
-
কিছু বিকাশকারী একবার একটি নির্দিষ্ট পরিস্থিতির জন্য ক্যাশের নিজস্ব বৈকল্পিক তৈরি করেছিলেন (কারণ অন্য কিছুই উপযুক্ত ছিল না)। পরবর্তীতে, পরবর্তী প্রকল্পে যাতে কোনো বিশেষ ক্যাশে লজিক জড়িত ছিল না, তারা তৈরি লাইব্রেরি (উদাহরণস্বরূপ, Ehcache) ব্যবহার করার পরিবর্তে তাদের বৈকল্পিক আবার ব্যবহার করে। ফলাফলটি ছিল একগুচ্ছ বাগ এবং অসঙ্গতি, সেইসাথে প্রচুর সময় নষ্ট এবং ভাজা স্নায়ু।
যে কেউ এই বিরোধী প্যাটার্ন জন্য পড়তে পারেন. আপনি যদি একজন শিক্ষানবিস হন, তাহলে আপনি ডিজাইন প্যাটার্ন সম্পর্কে জ্ঞানী নাও হতে পারেন। এর ফলে আপনি যেভাবে আয়ত্ত করেছেন সেভাবেই সব সমস্যার সমাধান করার চেষ্টা করতে পারেন। আমরা যদি পেশাদারদের কথা বলি, তাহলে আমরা একে বলি পেশাদার বিকৃতি বা nerdview। আপনার নিজের পছন্দের নকশার প্যাটার্ন রয়েছে এবং সঠিকটি ব্যবহার করার পরিবর্তে, আপনি আপনার পছন্দেরটি ব্যবহার করেন, ধরে নেন যে অতীতে একটি ভাল ফিট ভবিষ্যতে একই ফলাফলের গ্যারান্টি দেয়।
এই বিপত্তি অত্যন্ত দুঃখজনক ফলাফল আনতে পারে — একটি খারাপ, অস্থির, এবং বাস্তবায়ন বজায় রাখা কঠিন থেকে প্রকল্পের সম্পূর্ণ ব্যর্থতা পর্যন্ত। সমস্ত রোগের জন্য যেমন একটি বড়ি নেই, তেমনি সমস্ত অনুষ্ঠানের জন্য একটি নকশার প্যাটার্ন নেই।
9. অকাল অপ্টিমাইজেশান
অকাল অপ্টিমাইজেশান হল একটি বিরোধী প্যাটার্ন যার নাম নিজেই কথা বলে।10. স্প্যাগেটি কোড
স্প্যাগেটি কোড হল এমন একটি অ্যান্টি-প্যাটার্ন যা কোড দ্বারা সংজ্ঞায়িত করা হয় যা দুর্বলভাবে কাঠামোগত, বিভ্রান্তিকর এবং বোঝা কঠিন, যার মধ্যে সব ধরনের শাখা রয়েছে, যেমন মোড়ানো ব্যতিক্রম, শর্ত এবং লুপ। পূর্বে, গোটো অপারেটর ছিল এই প্যাটার্ন বিরোধী প্রধান সহযোগী। Goto বিবৃতি সত্যিই আর ব্যবহার করা হয় না, যা আনন্দের সাথে সংশ্লিষ্ট অসুবিধা এবং সমস্যাগুলিকে দূর করে।public boolean someDifficultMethod(List<String> XMLAttrList) {
...
int prefix = stringPool.getPrefixForQName(elementType);
int elementURI;
try {
if (prefix == -1) {
...
if (elementURI != -1) {
stringPool.setURIForQName(...);
}
} else {
...
if (elementURI == -1) {
...
}
}
} catch (Exception e) {
return false;
}
if (attrIndex != -1) {
int index = attrList.getFirstAttr(attrIndex);
while (index != -1) {
int attName = attrList.getAttrName(index);
if (!stringPool.equalNames(...)){
...
if (attPrefix != namespacesPrefix) {
if (attPrefix == -1) {
...
} else {
if (uri == -1) {
...
}
stringPool.setURIForQName(attName, uri);
...
}
if (elementDepth >= 0) {
...
}
elementDepth++;
if (elementDepth == fElementTypeStack.length) {
...
}
...
return contentSpecType == fCHILDRENSymbol;
}
}
}
}
}
এটা ভয়ঙ্কর দেখায়, তাই না? দুর্ভাগ্যবশত, এটি সবচেয়ে সাধারণ অ্যান্টি-প্যাটার্ন :( এমনকি যে ব্যক্তি এই ধরনের কোড লেখেন তিনিও ভবিষ্যতে এটি বুঝতে সক্ষম হবেন না৷ অন্যান্য বিকাশকারীরা যারা কোডটি দেখেন তারা মনে করবেন, "ঠিক আছে, যদি এটি কাজ করে তবে ঠিক আছে — এটি স্পর্শ না করাই ভালো।" প্রায়শই, একটি পদ্ধতি প্রাথমিকভাবে সহজ এবং খুব স্বচ্ছ হয়, কিন্তু নতুন প্রয়োজনীয়তা যুক্ত হওয়ার সাথে সাথে পদ্ধতিটি ধীরে ধীরে আরও বেশি শর্তসাপেক্ষ বিবৃতি দিয়ে জড়ো করা হয়, এটিকে এর মতো একটি দানবীয়তায় পরিণত করে। প্রদর্শিত হয়, আপনাকে এটি সম্পূর্ণরূপে বা অন্ততপক্ষে সবচেয়ে বিভ্রান্তিকর অংশগুলিকে রিফ্যাক্টর করতে হবে৷ সাধারণত, একটি প্রকল্পের সময় নির্ধারণ করার সময়, রিফ্যাক্টরিংয়ের জন্য সময় বরাদ্দ করা হয়, উদাহরণস্বরূপ, স্প্রিন্ট সময়ের 30% রিফ্যাক্টরিং এবং পরীক্ষার জন্য৷ অবশ্যই, এটি অনুমান করে যে কোন তাড়াহুড়ো নেই (তবে কখন তা হয়)।এখানে _
11. ম্যাজিক সংখ্যা
ম্যাজিক সংখ্যা হল একটি অ্যান্টি-প্যাটার্ন যেখানে সমস্ত ধরণের ধ্রুবক তাদের উদ্দেশ্য বা অর্থের কোন ব্যাখ্যা ছাড়াই একটি প্রোগ্রামে ব্যবহার করা হয়। অর্থাৎ, তারা সাধারণত খারাপভাবে নামকরণ করা হয় বা চরম ক্ষেত্রে, মন্তব্যগুলি কী বা কেন তা ব্যাখ্যা করে কোনও মন্তব্য নেই। স্প্যাগেটি কোডের মতো, এটি সবচেয়ে সাধারণ অ্যান্টি-প্যাটার্নগুলির মধ্যে একটি। যে কেউ কোডটি লেখেননি তার জাদু সংখ্যা বা তারা কীভাবে কাজ করে সে সম্পর্কে ধারণা থাকতে পারে বা নাও থাকতে পারে (এবং সময়ের সাথে সাথে লেখক নিজেই সেগুলি ব্যাখ্যা করতে সক্ষম হবেন না)। ফলস্বরূপ, একটি সংখ্যা পরিবর্তন বা সরানোর ফলে কোডটি জাদুকরীভাবে একসাথে কাজ করা বন্ধ করে দেয়। উদাহরণস্বরূপ, 36 এবং 73. এই বিরোধী প্যাটার্ন মোকাবেলা করতে, আমি একটি কোড পর্যালোচনা সুপারিশ. আপনার কোডটি বিকাশকারীদের দ্বারা দেখা উচিত যারা কোডের প্রাসঙ্গিক বিভাগে জড়িত নয়৷ তাদের চোখ সতেজ হবে এবং তাদের প্রশ্ন থাকবে: এটি কী এবং কেন আপনি এটি করলেন? এবং অবশ্যই, আপনাকে ব্যাখ্যামূলক নাম ব্যবহার করতে হবে বা মন্তব্য করতে হবে।12. কপি-এন্ড-পেস্ট প্রোগ্রামিং
কপি-এন্ড-পেস্ট প্রোগ্রামিং হল একটি অ্যান্টি-প্যাটার্ন যেখানে অন্য কারও কোড চিন্তাহীনভাবে কপি এবং পেস্ট করা হয়, সম্ভবত অপ্রত্যাশিত পার্শ্ব প্রতিক্রিয়া হতে পারে। উদাহরণস্বরূপ, গাণিতিক গণনা বা জটিল অ্যালগরিদমগুলির সাথে কপি এবং পেস্ট করার পদ্ধতি যা আমরা পুরোপুরি বুঝতে পারি না। এটি আমাদের নির্দিষ্ট ক্ষেত্রে কাজ করতে পারে, কিন্তু কিছু অন্যান্য পরিস্থিতিতে এটি সমস্যা হতে পারে। ধরুন একটি অ্যারের সর্বোচ্চ সংখ্যা নির্ধারণ করার জন্য আমার একটি পদ্ধতি দরকার। ইন্টারনেটের চারপাশে গুঞ্জন, আমি এই সমাধান খুঁজে পেয়েছি:public static int max(int[] array) {
int max = 0;
for(int i = 0; i < array.length; i++) {
if (Math.abs(array[i]) > max){
max = array[i];
}
}
return max;
}
আমরা 3, 6, 1, 4, এবং 2 নম্বরগুলির সাথে একটি অ্যারে পাই এবং পদ্ধতিটি 6 প্রদান করে। দুর্দান্ত, আসুন এটি রাখা যাক! কিন্তু পরে আমরা 2.5, -7, 2, এবং 3 সমন্বিত একটি অ্যারে পাই এবং তারপরে আমাদের ফলাফল -7 হয়। আর এই ফলাফল ভালো নয়। এখানে সমস্যা হল Math.abs() পরম মান প্রদান করে। এই সম্পর্কে অজ্ঞতা বিপর্যয়ের দিকে নিয়ে যায়, তবে শুধুমাত্র নির্দিষ্ট পরিস্থিতিতে। সমাধানটি গভীরভাবে না বুঝে, এমন অনেক ক্ষেত্রে আছে যা আপনি যাচাই করতে পারবেন না। অনুলিপি করা কোডটি অ্যাপ্লিকেশনের অভ্যন্তরীণ কাঠামোর বাইরেও যেতে পারে, উভয় শৈলীগতভাবে এবং আরও মৌলিক, স্থাপত্য স্তরে। এই ধরনের কোড পড়া এবং বজায় রাখা আরও কঠিন হবে। এবং অবশ্যই, আমাদের ভুলে যাওয়া উচিত নয় যে সরাসরি অন্য কারো কোড অনুলিপি করা একটি বিশেষ ধরনের চুরি।
13. চাকা পুনরায় উদ্ভাবন
চাকা পুনরায় উদ্ভাবন করা একটি অ্যান্টি-প্যাটার্ন যা কখনও কখনও বর্গাকার চাকা পুনঃউদ্ভাবন হিসাবেও পরিচিত. মোটকথা, এই টেমপ্লেটটি উপরে বিবেচিত কপি-এবং-পেস্ট-বিরোধী প্যাটার্নের বিপরীত। এই অ্যান্টি-প্যাটার্নে, বিকাশকারী একটি সমস্যার জন্য তার নিজস্ব সমাধান প্রয়োগ করে যার সমাধান ইতিমধ্যেই বিদ্যমান। কখনও কখনও এই বিদ্যমান সমাধানগুলি প্রোগ্রামার যা আবিষ্কার করে তার চেয়ে ভাল। প্রায়শই, এটি শুধুমাত্র হারিয়ে যাওয়া সময় এবং কম উত্পাদনশীলতার দিকে পরিচালিত করে: প্রোগ্রামার কোনও সমাধান খুঁজে নাও পেতে পারে বা এমন একটি সমাধান খুঁজে পেতে পারে যা সেরা থেকে অনেক দূরে। এটি বলেছে, আমরা একটি স্বাধীন সমাধান তৈরি করার সম্ভাবনাকে উড়িয়ে দিতে পারি না, কারণ এটি করা প্রোগ্রামিং কপি-এন্ড-পেস্ট করার একটি সরাসরি রাস্তা। প্রোগ্রামারকে নির্দিষ্ট প্রোগ্রামিং কাজগুলির দ্বারা পরিচালিত হওয়া উচিত যা সেগুলিকে দক্ষতার সাথে সমাধান করার জন্য উদ্ভূত হয়, তা রেডিমেড সমাধান ব্যবহার করে বা কাস্টম সমাধান তৈরি করে। খুব প্রায়ই, এই অ্যান্টি-প্যাটার্ন ব্যবহার করার কারণ হল তাড়াহুড়ো। ফলাফল একটি অগভীর বিশ্লেষণ (অনুসন্ধান) রেডিমেড সমাধান. বর্গাকার চাকা পুনরায় উদ্ভাবন করা এমন একটি ক্ষেত্রে যেখানে বিবেচনাধীন অ্যান্টি-প্যাটার্নের একটি নেতিবাচক ফলাফল রয়েছে। যে, প্রকল্পের একটি কাস্টম সমাধান প্রয়োজন, এবং বিকাশকারী এটি তৈরি করে, কিন্তু খারাপভাবে। একই সময়ে, একটি ভাল বিকল্প ইতিমধ্যেই বিদ্যমান এবং অন্যরা এটি সফলভাবে ব্যবহার করছে। নীচের লাইন: একটি বিশাল পরিমাণ সময় নষ্ট হয়. প্রথমত, আমরা এমন কিছু তৈরি করি যা কাজ করে না। তারপরে আমরা এটিকে রিফ্যাক্টর করার চেষ্টা করি এবং অবশেষে আমরা এটিকে এমন কিছু দিয়ে প্রতিস্থাপন করি যা আগে থেকেই ছিল। একটি উদাহরণ হল আপনার নিজস্ব কাস্টম ক্যাশে বাস্তবায়ন করা যখন প্রচুর বাস্তবায়ন ইতিমধ্যে বিদ্যমান। আপনি একজন প্রোগ্রামার হিসাবে যতই প্রতিভাবান হোন না কেন, আপনার মনে রাখা উচিত যে একটি বর্গাকার চাকা নতুন করে উদ্ভাবন করা অন্তত সময়ের অপচয়। এবং, আপনি জানেন, সময় হল সবচেয়ে মূল্যবান সম্পদ।14. ইয়ো-ইয়ো সমস্যা
ইয়ো -ইয়ো সমস্যা হল একটি অ্যান্টি-প্যাটার্ন যেখানে অ্যাপ্লিকেশনের গঠন অত্যধিক ফ্র্যাগমেন্টেশনের (উদাহরণস্বরূপ, একটি অত্যধিক উপবিভক্ত উত্তরাধিকার শৃঙ্খল) কারণে অত্যধিক জটিল। "ইয়ো-ইয়ো সমস্যা" দেখা দেয় যখন আপনাকে এমন একটি প্রোগ্রাম বুঝতে হবে যার উত্তরাধিকার শ্রেণিবিন্যাস দীর্ঘ এবং জটিল, গভীরভাবে নেস্টেড মেথড কল তৈরি করে। ফলস্বরূপ, প্রোগ্রামারদের প্রোগ্রামের আচরণ পরিদর্শন করার জন্য বিভিন্ন শ্রেণী এবং পদ্ধতির মধ্যে নেভিগেট করতে হবে। এই অ্যান্টি-প্যাটার্নের নামটি খেলনাটির নাম থেকে এসেছে। একটি উদাহরণ হিসাবে, আসুন নিম্নলিখিত উত্তরাধিকার চেইনটি দেখি: আমাদের একটি প্রযুক্তি ইন্টারফেস রয়েছে:public interface Technology {
void turnOn();
}
ট্রান্সপোর্ট ইন্টারফেস এটি উত্তরাধিকারসূত্রে পেয়েছে:
public interface Transport extends Technology {
boolean fillUp();
}
এবং তারপরে আমাদের আরেকটি ইন্টারফেস আছে, গ্রাউন্ড ট্রান্সপোর্ট:
public interface GroundTransportation extends Transport {
void startMove();
void brake();
}
এবং সেখান থেকে, আমরা একটি বিমূর্ত কার ক্লাস পাই:
public abstract class Car implements GroundTransportation {
@Override
public boolean fillUp() {
/* some implementation */
return true;
}
@Override
public void turnOn() {
/* some implementation */
}
public boolean openTheDoor() {
/* some implementation */
return true;
}
public abstract void fixCar();
}
পরবর্তী বিমূর্ত ভক্সওয়াগেন ক্লাস:
public abstract class Volkswagen extends Car {
@Override
public void startMove() {
/* some implementation */
}
@Override
public void brake() {
/* some implementation */
}
}
এবং অবশেষে, একটি নির্দিষ্ট মডেল:
public class VolkswagenAmarok extends Volkswagen {
@Override
public void fixCar(){
/* some implementation */
}
}
এই চেইনটি আমাদের এই ধরনের প্রশ্নের উত্তর খুঁজতে বাধ্য করে:
-
কত পদ্ধতি
VolkswagenAmarok
আছে? -
সর্বাধিক বিমূর্ততা অর্জনের জন্য প্রশ্ন চিহ্নের পরিবর্তে কি ধরনের সন্নিবেশ করা উচিত:
? someObj = new VolkswagenAmarok(); someObj.brake();
15. দুর্ঘটনাজনিত জটিলতা
অপ্রয়োজনীয় জটিলতা একটি বিরোধী প্যাটার্ন যেখানে অপ্রয়োজনীয় জটিলতাগুলি সমাধানের জন্য প্রবর্তিত হয়।public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description)throws Exception {
switch (type){
case CAR:
jdbcTemplate.update(CREATE_RELATION_WITH_CAR, languageId, serviceId, description);
case USER:
jdbcTemplate.update(CREATE_RELATION_WITH_USER, languageId, serviceId, description);
case FILE:
jdbcTemplate.update(CREATE_RELATION_WITH_FILE, languageId, serviceId, description);
case PLAN:
jdbcTemplate.update(CREATE_RELATION_WITH_PLAN, languageId, serviceId, description);
case CUSTOMER:
jdbcTemplate.update(CREATE_RELATION_WITH_CUSTOMER, languageId, serviceId, description);
default:
throw new Exception();
}
}
এবং সেই অনুযায়ী, আমাদের এই enum আছে:
public enum ServiceType {
CAR(),
USER(),
FILE(),
PLAN(),
CUSTOMER()
}
সবকিছু সহজ এবং ভাল বলে মনে হচ্ছে... কিন্তু অন্যান্য পদ্ধতি সম্পর্কে কি? প্রকৃতপক্ষে, তাদের সকলের কাছে একগুচ্ছ switch
বিবৃতি এবং প্রায় অভিন্ন ডাটাবেস প্রশ্নগুলির একটি গুচ্ছ থাকবে, যা আমাদের ক্লাসকে ব্যাপকভাবে জটিল করে তুলবে। কিভাবে এই সব সহজ করা যেতে পারে? আমাদের enum একটু আপগ্রেড করা যাক:
@Getter
@AllArgsConstructor
public enum ServiceType {
CAR("cars_descriptions", "car_id"),
USER("users_descriptions", "user_id"),
FILE("files_descriptions", "file_id"),
PLAN("plans_descriptions", "plan_id"),
CUSTOMER("customers_descriptions", "customer_id");
private String tableName;
private String columnName;
}
এখন প্রতিটি প্রকারের টেবিলের মূল ক্ষেত্রগুলির নাম রয়েছে। ফলস্বরূপ, একটি বিবরণ তৈরি করার পদ্ধতিটি হয়ে যায়:
private static final String CREATE_RELATION_WITH_SERVICE = "INSERT INTO %s(language_id, %s, description) VALUES (?, ?, ?)";
public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description) {
jdbcTemplate.update(String.format(CREATE_RELATION_WITH_SERVICE, type.getTableName(), type.getColumnName()), languageId, serviceId, description);
}
সুবিধাজনক, সহজ এবং কমপ্যাক্ট, আপনি কি মনে করেন না? একজন ভাল বিকাশকারীর ইঙ্গিতটি এমনকি কত ঘন ঘন নিদর্শন ব্যবহার করে তা নয়, বরং তিনি কত ঘন ঘন অ্যান্টি-প্যাটার্ন এড়িয়ে চলেন। অজ্ঞতা সবচেয়ে খারাপ শত্রু, কারণ আপনার শত্রুদের দেখতে হবে। ওয়েল, যে সব আমি আজকের জন্য আছে. ধন্যবাদ সবাইকে! :)