জাভাস্ক্রিপ্ট ডেকোরেটরস সম্পর্কে জানুন: মেটাডেটা যোগ করুন, ক্লাস/মেথড রূপান্তর করুন এবং আপনার কোডের কার্যকারিতা একটি পরিচ্ছন্ন, ঘোষণামূলক উপায়ে উন্নত করুন।
জাভাস্ক্রিপ্ট ডেকোরেটরস: মেটাডেটা এবং রূপান্তর
জাভাস্ক্রিপ্ট ডেকোরেটরস, যা পাইথন এবং জাভার মতো ভাষা থেকে অনুপ্রাণিত একটি ফিচার, এটি ক্লাস, মেথড, প্রপার্টি এবং প্যারামিটারে মেটাডেটা যোগ এবং রূপান্তর করার জন্য একটি শক্তিশালী ও প্রকাশযোগ্য উপায় সরবরাহ করে। এটি কোডের কার্যকারিতা বাড়ানোর এবং উদ্বেগের পৃথকীকরণে (separation of concerns) উৎসাহ দেওয়ার জন্য একটি পরিচ্ছন্ন, ঘোষণামূলক সিনট্যাক্স প্রদান করে। যদিও জাভাস্ক্রিপ্ট ইকোসিস্টেমে এটি এখনও তুলনামূলকভাবে নতুন, ডেকোরেটরস জনপ্রিয়তা অর্জন করছে, বিশেষত অ্যাঙ্গুলার (Angular) এর মতো ফ্রেমওয়ার্ক এবং লাইব্রেরিগুলিতে যা ডিপেন্ডেন্সি ইনজেকশন এবং অন্যান্য উন্নত বৈশিষ্ট্যের জন্য মেটাডেটা ব্যবহার করে। এই নিবন্ধে জাভাস্ক্রিপ্ট ডেকোরেটরসের মূল বিষয়গুলি, তাদের প্রয়োগ এবং আরও রক্ষণাবেক্ষণযোগ্য ও প্রসারণযোগ্য কোডবেস তৈরির সম্ভাবনা অন্বেষণ করা হয়েছে।
জাভাস্ক্রিপ্ট ডেকোরেটরস কী?
মূলত, ডেকোরেটর হলো বিশেষ ধরনের ডিক্লারেশন যা ক্লাস, মেথড, অ্যাক্সেসর, প্রপার্টি বা প্যারামিটারের সাথে সংযুক্ত করা যায়। তারা @expression
সিনট্যাক্স ব্যবহার করে, যেখানে expression
অবশ্যই একটি ফাংশনে রূপান্তরিত হতে হবে যা রানটাইমে ডেকোরেটেড ডিক্লারেশন সম্পর্কে তথ্যসহ কল করা হবে। ডেকোরেটরস মূলত এমন ফাংশন হিসাবে কাজ করে যা ডেকোরেটেড এলিমেন্টের আচরণ পরিবর্তন বা প্রসারিত করে।
ডেকোরেটরসকে সরাসরি পরিবর্তন না করে বিদ্যমান কোডকে র্যাপ (wrap) বা অগমেন্ট (augment) করার একটি উপায় হিসাবে ভাবুন। সফটওয়্যার ডিজাইনে এই নীতিটি ডেকোরেটর প্যাটার্ন হিসাবে পরিচিত, যা আপনাকে একটি অবজেক্টে গতিশীলভাবে কার্যকারিতা যোগ করার সুযোগ দেয়।
ডেকোরেটরস সক্রিয় করা
যদিও ডেকোরেটরস ECMAScript স্ট্যান্ডার্ডের একটি অংশ, তবে বেশিরভাগ জাভাস্ক্রিপ্ট পরিবেশে এগুলি ডিফল্টরূপে সক্রিয় থাকে না। সেগুলি ব্যবহার করার জন্য, আপনাকে সাধারণত আপনার বিল্ড টুলস কনফিগার করতে হবে। এখানে কিছু সাধারণ পরিবেশে ডেকোরেটরস সক্রিয় করার উপায় দেখানো হলো:
- TypeScript: টাইপস্ক্রিপ্টে ডেকোরেটরস নেটিভভাবে সমর্থিত। আপনার
tsconfig.json
ফাইলেexperimentalDecorators
কম্পাইলার অপশনটিtrue
তে সেট করা আছে কিনা তা নিশ্চিত করুন:
{
"compilerOptions": {
"target": "esnext",
"experimentalDecorators": true,
"emitDecoratorMetadata": true, // Optional, but often useful
"module": "commonjs", // Or another module system like "es6" or "esnext"
"moduleResolution": "node"
}
}
- Babel: আপনি যদি ব্যাবেল (Babel) ব্যবহার করেন, তবে আপনাকে
@babel/plugin-proposal-decorators
প্লাগইনটি ইনস্টল এবং কনফিগার করতে হবে:
npm install --save-dev @babel/plugin-proposal-decorators
তারপরে, আপনার ব্যাবেল কনফিগারেশনে (যেমন, .babelrc
বা babel.config.js
) প্লাগইনটি যোগ করুন:
{
"plugins": [["@babel/plugin-proposal-decorators", { "version": "2023-05" }]]
}
version
অপশনটি গুরুত্বপূর্ণ এবং এটি আপনার টার্গেট করা ডেকোরেটরস প্রস্তাবনার সংস্করণের সাথে মিলতে হবে। সর্বশেষ প্রস্তাবিত সংস্করণের জন্য ব্যাবেল প্লাগইন ডকুমেন্টেশন দেখুন।
ডেকোরেটরসের প্রকারভেদ
বিভিন্ন ধরণের ডেকোরেটর রয়েছে, প্রত্যেকটি নির্দিষ্ট এলিমেন্টের জন্য ডিজাইন করা হয়েছে:
- ক্লাস ডেকোরেটরস: ক্লাসের উপর প্রয়োগ করা হয়।
- মেথড ডেকোরেটরস: ক্লাসের ভেতরের মেথডের উপর প্রয়োগ করা হয়।
- অ্যাক্সেসর ডেকোরেটরস: গেটার বা সেটার অ্যাক্সেসরের উপর প্রয়োগ করা হয়।
- প্রপার্টি ডেকোরেটরস: ক্লাসের প্রপার্টির উপর প্রয়োগ করা হয়।
- প্যারামিটার ডেকোরেটরস: মেথড বা কনস্ট্রাক্টরের প্যারামিটারের উপর প্রয়োগ করা হয়।
ক্লাস ডেকোরেটরস
ক্লাস ডেকোরেটরস একটি ক্লাসের কনস্ট্রাক্টরের উপর প্রয়োগ করা হয় এবং এটি ক্লাসের সংজ্ঞা পর্যবেক্ষণ, পরিবর্তন বা প্রতিস্থাপন করতে ব্যবহার করা যেতে পারে। তারা তাদের একমাত্র আর্গুমেন্ট হিসাবে ক্লাস কনস্ট্রাক্টরটি গ্রহণ করে।
উদাহরণ:
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
// Attempting to add properties to the sealed class or its prototype will fail
এই উদাহরণে, @sealed
ডেকোরেটরটি Greeter
ক্লাস এবং তার প্রোটোটাইপে আরও পরিবর্তন প্রতিরোধ করে। এটি অপরিবর্তনীয়তা (immutability) নিশ্চিত করতে বা দুর্ঘটনাজনিত পরিবর্তন রোধ করতে কার্যকর হতে পারে।
মেথড ডেকোরেটরস
মেথড ডেকোরেটরস ক্লাসের ভেতরের মেথডগুলিতে প্রয়োগ করা হয়। তারা তিনটি আর্গুমেন্ট গ্রহণ করে:
target
: ক্লাসের প্রোটোটাইপ (ইনস্ট্যান্স মেথডের জন্য) অথবা ক্লাস কনস্ট্রাক্টর (স্ট্যাটিক মেথডের জন্য)।propertyKey
: যে মেথডটি ডেকোরেট করা হচ্ছে তার নাম।descriptor
: মেথডটির প্রপার্টি ডেসক্রিপ্টর।
উদাহরণ:
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${propertyKey} with arguments: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
console.log(`Method ${propertyKey} returned: ${result}`);
return result;
};
return descriptor;
}
class Calculator {
@log
add(x: number, y: number) {
return x + y;
}
}
const calculator = new Calculator();
calculator.add(2, 3); // Output: Calling add with arguments: [2,3]
// Method add returned: 5
@log
ডেকোরেটরটি add
মেথডের আর্গুমেন্টস এবং রিটার্ন ভ্যালু লগ করে। এটি একটি সহজ উদাহরণ যা দেখায় কিভাবে মেথড ডেকোরেটরস লগিং, প্রোফাইলিং বা অন্যান্য ক্রস-কাটিং কনসার্নের জন্য ব্যবহার করা যেতে পারে।
অ্যাক্সেসর ডেকোরেটরস
অ্যাক্সেসর ডেকোরেটরস মেথড ডেকোরেটরসের মতোই, কিন্তু এগুলি গেটার বা সেটার অ্যাক্সেসরের উপর প্রয়োগ করা হয়। এগুলিও একই তিনটি আর্গুমেন্ট গ্রহণ করে: target
, propertyKey
, এবং descriptor
।
উদাহরণ:
function configurable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}
class Point {
private _x: number;
private _y: number;
constructor(x: number, y: number) {
this._x = x;
this._y = y;
}
@configurable(false)
get x() {
return this._x;
}
set x(value: number) {
this._x = value;
}
}
const point = new Point(1, 2);
// Object.defineProperty(point, 'x', { configurable: true }); // Would throw an error because 'x' is not configurable
@configurable(false)
ডেকোরেটরটি x
গেটারকে পুনরায় কনফিগার করা থেকে বিরত রাখে, ফলে এটি নন-কনফিগারেবল হয়ে যায়।
প্রপার্টি ডেকোরেটরস
প্রপার্টি ডেকোরেটরস ক্লাসের প্রপার্টির উপর প্রয়োগ করা হয়। তারা দুটি আর্গুমেন্ট গ্রহণ করে:
target
: ক্লাসের প্রোটোটাইপ (ইনস্ট্যান্স প্রপার্টির জন্য) অথবা ক্লাস কনস্ট্রাক্টর (স্ট্যাটিক প্রপার্টির জন্য)।propertyKey
: যে প্রপার্টিটি ডেকোরেট করা হচ্ছে তার নাম।
উদাহরণ:
function readonly(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
writable: false,
});
}
class Person {
@readonly
name: string;
constructor(name: string) {
this.name = name;
}
}
const person = new Person("Alice");
// person.name = "Bob"; // This will cause an error in strict mode because 'name' is readonly
@readonly
ডেকোরেটরটি name
প্রপার্টিকে শুধুমাত্র পঠনযোগ্য (read-only) করে তোলে, যা ইনিশিয়ালাইজেশনের পরে এটিকে পরিবর্তন করা থেকে বিরত রাখে।
প্যারামিটার ডেকোরেটরস
প্যারামিটার ডেকোরেটরস মেথড বা কনস্ট্রাক্টরের প্যারামিটারের উপর প্রয়োগ করা হয়। তারা তিনটি আর্গুমেন্ট গ্রহণ করে:
target
: ক্লাসের প্রোটোটাইপ (ইনস্ট্যান্স মেথডের জন্য) অথবা ক্লাস কনস্ট্রাক্টর (স্ট্যাটিক মেথড বা কনস্ট্রাক্টরের জন্য)।propertyKey
: মেথড বা কনস্ট্রাক্টরের নাম।parameterIndex
: প্যারামিটার তালিকার মধ্যে প্যারামিটারের সূচক (index)।
প্যারামিটার ডেকোরেটরস প্রায়ই রিফ্লেকশনের সাথে ব্যবহার করা হয় একটি ফাংশনের প্যারামিটার সম্পর্কে মেটাডেটা সংরক্ষণ করার জন্য। এই মেটাডেটা রানটাইমে ডিপেন্ডেন্সি ইনজেকশন বা অন্যান্য উদ্দেশ্যে ব্যবহার করা যেতে পারে। এটি সঠিকভাবে কাজ করার জন্য, আপনাকে আপনার tsconfig.json
ফাইলে emitDecoratorMetadata
কম্পাইলার অপশনটি সক্রিয় করতে হবে।
উদাহরণ (reflect-metadata
ব্যবহার করে):
import 'reflect-metadata';
function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {
let existingRequiredParameters: number[] = Reflect.getOwnMetadata("required", target, propertyKey) || [];
existingRequiredParameters.push(parameterIndex);
Reflect.defineMetadata("required", existingRequiredParameters, target, propertyKey);
}
function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor) {
let method = descriptor.value!;
descriptor.value = function (...args: any[]) {
let requiredParameters: number[] = Reflect.getOwnMetadata("required", target, propertyName);
if (requiredParameters) {
for (let parameterIndex of requiredParameters) {
if (args[parameterIndex] === null || args[parameterIndex] === undefined) {
throw new Error(`Missing required argument at index ${parameterIndex}`);
}
}
}
return method.apply(this, args);
};
}
class User {
name: string;
age: number;
constructor(@required name: string, public surname: string, @required age: number) {
this.name = name;
this.age = age;
}
@validate
greet(prefix: string, @required salutation: string): string {
return `${prefix} ${salutation} ${this.name}`;
}
}
// Usage
try {
const user1 = new User("John", "Doe", 30);
console.log(user1.greet("Mr.", "Hello"));
const user2 = new User(undefined as any, "Doe", null as any);
} catch (error) {
console.error(error.message);
}
try {
const user = new User("John", "Doe", 30);
console.log(user.greet("Mr.", undefined as any));
} catch (error) {
console.error(error.message);
}
এই উদাহরণে, @required
ডেকোরেটরটি প্যারামিটারগুলিকে প্রয়োজনীয় হিসাবে চিহ্নিত করে। এরপর @validate
ডেকোরেটরটি রিফ্লেকশন (reflect-metadata
এর মাধ্যমে) ব্যবহার করে মেথড কল করার আগে প্রয়োজনীয় প্যারামিটারগুলি উপস্থিত আছে কিনা তা পরীক্ষা করে। এই উদাহরণটি প্রাথমিক ব্যবহার দেখায়, এবং প্রোডাকশন পরিস্থিতিতে একটি শক্তিশালী প্যারামিটার ভ্যালিডেশন তৈরি করার পরামর্শ দেওয়া হয়।
reflect-metadata
ইনস্টল করতে:
npm install reflect-metadata --save
মেটাডেটার জন্য ডেকোরেটরস ব্যবহার
ডেকোরেটরসের অন্যতম প্রধান ব্যবহার হলো ক্লাস এবং তাদের সদস্যদের সাথে মেটাডেটা সংযুক্ত করা। এই মেটাডেটা রানটাইমে বিভিন্ন উদ্দেশ্যে ব্যবহার করা যেতে পারে, যেমন ডিপেন্ডেন্সি ইনজেকশন, সিরিয়ালাইজেশন এবং ভ্যালিডেশন। reflect-metadata
লাইব্রেরি মেটাডেটা সংরক্ষণ এবং পুনরুদ্ধারের জন্য একটি স্ট্যান্ডার্ড উপায় সরবরাহ করে।
উদাহরণ:
import 'reflect-metadata';
const TYPE_KEY = "design:type";
const PARAMTYPES_KEY = "design:paramtypes";
const RETURNTYPE_KEY = "design:returntype";
function Type(type: any) {
return Reflect.metadata(TYPE_KEY, type);
}
function LogType(target: any, propertyKey: string) {
const t = Reflect.getMetadata(TYPE_KEY, target, propertyKey);
console.log(`${target.constructor.name}.${propertyKey} type: ${t.name}`);
}
class Demo {
@LogType
public name: string;
constructor(name: string){
this.name = name;
}
}
ডেকোরেটর ফ্যাক্টরি
ডেকোরেটর ফ্যাক্টরি হলো এমন ফাংশন যা একটি ডেকোরেটর রিটার্ন করে। তারা আপনাকে ডেকোরেটরে আর্গুমেন্ট পাস করার সুযোগ দেয়, যা এটিকে আরও নমনীয় এবং পুনঃব্যবহারযোগ্য করে তোলে।
উদাহরণ:
function deprecated(deprecationReason: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.warn(`Method ${propertyKey} is deprecated: ${deprecationReason}`);
return originalMethod.apply(this, args);
};
return descriptor;
};
}
class LegacyComponent {
@deprecated("Use the newMethod instead.")
oldMethod() {
console.log("Old method called");
}
newMethod() {
console.log("New method called");
}
}
const component = new LegacyComponent();
component.oldMethod(); // Output: Method oldMethod is deprecated: Use the newMethod instead.
// Old method called
@deprecated
ডেকোরেটর ফ্যাক্টরিটি একটি অবচয় বার্তা (deprecation message) আর্গুমেন্ট হিসেবে নেয় এবং ডেকোরেটেড মেথডটি কল করা হলে একটি সতর্কতা লগ করে। এটি আপনাকে মেথডগুলিকে অপ্রচলিত হিসাবে চিহ্নিত করতে এবং ডেভেলপারদের নতুন বিকল্পে স্থানান্তরিত করার জন্য নির্দেশনা প্রদান করতে সাহায্য করে।
বাস্তব-জগতের ব্যবহারের ক্ষেত্র
আধুনিক জাভাস্ক্রিপ্ট ডেভেলপমেন্টে ডেকোরেটরসের ব্যাপক প্রয়োগ রয়েছে:
- ডিপেন্ডেন্সি ইনজেকশন: অ্যাঙ্গুলারের মতো ফ্রেমওয়ার্কগুলি ডিপেন্ডেন্সি ইনজেকশনের জন্য ডেকোরেটরসের উপর ব্যাপকভাবে নির্ভর করে।
- রাউটিং: ওয়েব অ্যাপ্লিকেশনগুলিতে, কন্ট্রোলার এবং মেথডের জন্য রুট নির্ধারণ করতে ডেকোরেটরস ব্যবহার করা যেতে পারে।
- ভ্যালিডেশন: ইনপুট ডেটা যাচাই করতে এবং এটি নির্দিষ্ট মানদণ্ড পূরণ করে কিনা তা নিশ্চিত করতে ডেকোরেটরস ব্যবহার করা যেতে পারে।
- অথোরাইজেশন: নিরাপত্তা নীতি প্রয়োগ করতে এবং নির্দিষ্ট মেথড বা রিসোর্সে অ্যাক্সেস সীমাবদ্ধ করতে ডেকোরেটরস ব্যবহার করা যেতে পারে।
- লগিং এবং প্রোফাইলিং: উপরের উদাহরণগুলিতে যেমন দেখানো হয়েছে, কোড এক্সিকিউশনের লগিং এবং প্রোফাইলিংয়ের জন্য ডেকোরেটরস ব্যবহার করা যেতে পারে।
- স্টেট ম্যানেজমেন্ট: স্টেট পরিবর্তন হলে কম্পোনেন্টগুলি স্বয়ংক্রিয়ভাবে আপডেট করার জন্য ডেকোরেটরস স্টেট ম্যানেজমেন্ট লাইব্রেরির সাথে একীভূত হতে পারে।
ডেকোরেটরস ব্যবহারের সুবিধা
- কোডের পাঠযোগ্যতা বৃদ্ধি: ডেকোরেটরস কার্যকারিতা যোগ করার জন্য একটি ঘোষণামূলক সিনট্যাক্স প্রদান করে, যা কোডকে বোঝা এবং রক্ষণাবেক্ষণ করা সহজ করে তোলে।
- উদ্বেগের পৃথকীকরণ: ডেকোরেটরস আপনাকে মূল ব্যবসায়িক যুক্তি থেকে ক্রস-কাটিং কনসার্ন (যেমন, লগিং, ভ্যালিডেশন, অথোরাইজেশন) আলাদা করতে দেয়।
- পুনঃব্যবহারযোগ্যতা: ডেকোরেটরস একাধিক ক্লাস এবং মেথডে পুনরায় ব্যবহার করা যেতে পারে, যা কোডের পুনরাবৃত্তি কমায়।
- প্রসারণযোগ্যতা: ডেকোরেটরস বিদ্যমান কোডকে সরাসরি পরিবর্তন না করেই তার কার্যকারিতা বাড়ানো সহজ করে তোলে।
চ্যালেঞ্জ এবং বিবেচ্য বিষয়
- শেখার প্রতিবন্ধকতা: ডেকোরেটরস একটি তুলনামূলকভাবে নতুন ফিচার, এবং এটি কার্যকরভাবে ব্যবহার করতে শিখতে কিছু সময় লাগতে পারে।
- সামঞ্জস্যতা: নিশ্চিত করুন যে আপনার টার্গেট এনভায়রনমেন্ট ডেকোরেটরস সমর্থন করে এবং আপনি আপনার বিল্ড টুলস সঠিকভাবে কনফিগার করেছেন।
- ডিবাগিং: ডেকোরেটরস ব্যবহার করে এমন কোড ডিবাগ করা সাধারণ কোড ডিবাগ করার চেয়ে বেশি চ্যালেঞ্জিং হতে পারে, বিশেষ করে যদি ডেকোরেটরস জটিল হয়।
- অতিরিক্ত ব্যবহার: ডেকোরেটরসের অতিরিক্ত ব্যবহার এড়িয়ে চলুন, কারণ এটি আপনার কোডকে বোঝা এবং রক্ষণাবেক্ষণ করা কঠিন করে তুলতে পারে। নির্দিষ্ট উদ্দেশ্যে কৌশলগতভাবে সেগুলি ব্যবহার করুন।
- রানটাইম ওভারহেড: ডেকোরেটরস কিছু রানটাইম ওভারহেড তৈরি করতে পারে, বিশেষ করে যদি তারা জটিল অপারেশন সম্পাদন করে। পারফরম্যান্স-নির্ভর অ্যাপ্লিকেশনগুলিতে ডেকোরেটরস ব্যবহার করার সময় পারফরম্যান্সের প্রভাব বিবেচনা করুন।
উপসংহার
জাভাস্ক্রিপ্ট ডেকোরেটরস কোডের কার্যকারিতা বাড়ানো এবং উদ্বেগের পৃথকীকরণকে উৎসাহিত করার জন্য একটি শক্তিশালী টুল। ক্লাস, মেথড, প্রপার্টি এবং প্যারামিটারে মেটাডেটা যোগ এবং রূপান্তর করার জন্য একটি পরিচ্ছন্ন, ঘোষণামূলক সিনট্যাক্স প্রদান করে, ডেকোরেটরস আপনাকে আরও রক্ষণাবেক্ষণযোগ্য, পুনঃব্যবহারযোগ্য এবং প্রসারণযোগ্য কোডবেস তৈরি করতে সাহায্য করতে পারে। যদিও এগুলি শেখার ক্ষেত্রে কিছু প্রতিবন্ধকতা এবং সম্ভাব্য চ্যালেঞ্জ নিয়ে আসে, সঠিক প্রেক্ষাপটে ডেকোরেটরস ব্যবহারের সুবিধাগুলি তাৎপর্যপূর্ণ হতে পারে। জাভাস্ক্রিপ্ট ইকোসিস্টেম যেমন বিকশিত হতে থাকবে, ডেকোরেটরস আধুনিক জাভাস্ক্রিপ্ট ডেভেলপমেন্টের একটি ক্রমবর্ধমান গুরুত্বপূর্ণ অংশ হয়ে উঠবে।
আপনার বিদ্যমান কোডকে ডেকোরেটরস কীভাবে সহজ করতে পারে বা আপনাকে আরও প্রকাশযোগ্য এবং রক্ষণাবেক্ষণযোগ্য অ্যাপ্লিকেশন লিখতে সক্ষম করতে পারে তা অন্বেষণ করার কথা বিবেচনা করুন। সতর্ক পরিকল্পনা এবং তাদের ক্ষমতার একটি দৃঢ় বোঝার মাধ্যমে, আপনি আরও শক্তিশালী এবং স্কেলেবল জাভাস্ক্রিপ্ট সমাধান তৈরি করতে ডেকোরেটরসকে কাজে লাগাতে পারেন।