সুতরাং কোন মুহূর্তে কোন শ্রেণি অপরিবর্তনীয় হতে খুব জটিল হয়ে ওঠে?
আমার মতে আপনার দেখানো ভাষার মতো ছোট ছোট ক্লাসগুলি অপরিবর্তনীয় করে তোলা উচিত নয়। আমি এখানে ছোট ব্যবহার করছি এবং জটিল নয় , এমনকি যদি আপনি সেই শ্রেণিতে দশটি ক্ষেত্র যুক্ত করেন এবং এটি সত্যিই অভিনব অপারেশন করে তবে আমার সন্দেহ হয় যে এটি কিলোবাইট গ্রহণ করতে চলেছে একা মেগাবাইট একা গিগা বাইট দেয়, সুতরাং কোনও ফাংশন উদাহরণস্বরূপ ব্যবহার করে আপনার ক্লাস কেবলমাত্র বাহ্যিক পার্শ্ব প্রতিক্রিয়া সৃষ্টি করতে এড়াতে চাইলে মূলটিকে সংশোধন করা এড়াতে পুরো সামগ্রীর একটি সস্তা অনুলিপি তৈরি করতে পারে।
ধারাবাহিক ডেটা স্ট্রাকচারস
যেখানে আমি অপরিবর্তনীয়তার জন্য ব্যক্তিগত ব্যবহারটি এটি বৃহত্তর, কেন্দ্রীয় ডেটা স্ট্রাকচারের জন্য যা আপনি দেখিয়েছেন এমন শ্রেণীর উদাহরণগুলির মত একগুচ্ছ কিশোরী ডেটা সংগ্রহ করে যা মিলিয়ন সঞ্চয় করে NamedThings
। অবিচ্ছিন্ন এবং স্থায়ী ডাটা স্ট্রাকচারের সাথে সম্পর্কিত যা কেবলমাত্র কেবল পঠনযোগ্য অ্যাক্সেসের অনুমতি দেয় এমন একটি ইন্টারফেসের পিছনে থাকার ফলে, ধারকটির অন্তর্ভুক্ত উপাদানগুলি অ্যালিমেন্ট ক্লাস ( NamedThing
) এর সাথে মোকাবেলা না করেই অপরিবর্তনীয় হয়ে যায়।
সস্তা কপি
অবিচলিত ডেটা কাঠামো এর অঞ্চলগুলিকে পুরোপুরি অনুলিপি না করে মূলগুলিতে পরিবর্তনগুলি এড়ানো, এর অঞ্চলগুলিকে রূপান্তরিত এবং অনন্য করে তোলার অনুমতি দেয়। এটাই এর আসল সৌন্দর্য। আপনি যদি নির্লিপ্তভাবে এমন ফাংশনগুলি লিখতে চেয়েছিলেন যা পার্শ্ব প্রতিক্রিয়াগুলি এড়ায় যা কোনও ডেটা স্ট্রাকচারের সাথে মেমরির গিগাবাইট গ্রহণ করে এবং কেবল একটি মেগাবাইটের মেমরির মূল্য পরিবর্তন করে, তবে আপনাকে ইনপুটটির স্পর্শটি এড়াতে এবং সম্পূর্ণ নতুন ফিচারটি অনুলিপি করতে হবে আউটপুট। পার্শ্ব প্রতিক্রিয়া এড়াতে গিগাবাইটগুলি অনুলিপি করুন বা সেই দৃশ্যে পার্শ্ব প্রতিক্রিয়া সৃষ্টি করুন, আপনাকে দুটি অপ্রীতিকর পছন্দগুলির মধ্যে বেছে নিতে হবে।
অবিরাম ডেটা স্ট্রাকচারের সাহায্যে এটি আপনাকে এই জাতীয় ফাংশন লিখতে এবং পুরো ডেটা স্ট্রাকচারের অনুলিপি এড়াতে দেয়, কেবলমাত্র যদি আউটপুটটির জন্য একটি মেগাবাইট অতিরিক্ত মেমরির প্রয়োজন হয় তবে যদি আপনার ফাংশনটি কেবল একটি মেগাবাইটের স্মৃতির মূল্যকে রূপান্তরিত করে।
বোঝা
বোঝা হিসাবে, আমার ক্ষেত্রে অন্তত একটি তাত্ক্ষণিক আছে। আমার দরকার সেই বিল্ডাররা লোকেদের সম্পর্কে বা "স্থানান্তরকারীদের" কথা বলছে কারণ আমি তাদের বলি যে এটি বিশালভাবে ডেটা স্ট্রাকচারকে স্পর্শ না করেই কার্যকরভাবে রূপান্তর প্রকাশ করতে সক্ষম হতে। এর মতো কোড:
void transform_stuff(MutList<Stuff>& stuff, int first, int last)
{
// Transform stuff in the range, [first, last).
for (; first != last; ++first)
transform(stuff[first]);
}
... তাহলে এভাবে লিখতে হবে:
ImmList<Stuff> transform_stuff(ImmList<Stuff> stuff, int first, int last)
{
// Grab a "transient" (builder) list we can modify:
TransientList<Stuff> transient(stuff);
// Transform stuff in the range, [first, last)
// for the transient list.
for (; first != last; ++first)
transform(transient[first]);
// Commit the modifications to get and return a new
// immutable list.
return stuff.commit(transient);
}
কোডের এই দুটি অতিরিক্ত লাইনগুলির বিনিময়ে, ফাংশনটি এখন একই মূল তালিকার সাথে থ্রেডগুলিতে কল করা নিরাপদ, এটি কোনও পার্শ্ব প্রতিক্রিয়া সৃষ্টি করে না etc. ইত্যাদি কারণ এটি এই অপারেশনটিকে একটি অনিবার্য ব্যবহারকারীর ক্রিয়া হিসাবে তৈরি করা সত্যই সহজ করে তোলে পূর্বাবস্থায় ফিরে আসা পুরানো তালিকার একটি সস্তা অগভীর অনুলিপি সঞ্চয় করতে পারে।
ব্যতিক্রম-সুরক্ষা বা ত্রুটি পুনরুদ্ধার
এই জাতীয় প্রসঙ্গে যেমন অবিরাম ডেটা স্ট্রাকচার থেকে আমি যতটা উপকৃত হতে পারি তা সবাই উপকৃত হতে পারে না (আমার ভিএফএক্স ডোমেনের কেন্দ্রীয় ধারণাগুলি হ'ল আমি তাদের পূর্বাবস্থায় সিস্টেমে এবং অ-ধ্বংসাত্মক সম্পাদনায় এতো ব্যবহার খুঁজে পেয়েছি), তবে কেবল একটি ক্ষেত্রে প্রযোজ্য বিবেচনা করা প্রত্যেকটি ব্যতিক্রম-সুরক্ষা বা ত্রুটি পুনরুদ্ধার ।
আপনি যদি আসল মিউটেশন ফাংশনটি ব্যতিক্রম-নিরাপদ করতে চান তবে তার জন্য রোলব্যাক যুক্তি প্রয়োজন, যার জন্য সহজতম বাস্তবায়নের জন্য পুরো তালিকাটি অনুলিপি করা দরকার :
void transform_stuff(MutList<Stuff>& stuff, int first, int last)
{
// Make a copy of the whole massive gigabyte-sized list
// in case we encounter an exception and need to rollback
// changes.
MutList<Stuff> old_stuff = stuff;
try
{
// Transform stuff in the range, [first, last).
for (; first != last; ++first)
transform(stuff[first]);
}
catch (...)
{
// If the operation failed and ran into an exception,
// swap the original list with the one we modified
// to "undo" our changes.
stuff.swap(old_stuff);
throw;
}
}
এই মুহুর্তে ব্যতিক্রম-নিরাপদ মিউটেবল সংস্করণটি আরও বেশি গণনামূলকভাবে ব্যয়বহুল এবং "বিল্ডার" ব্যবহার করে অপরিবর্তনীয় সংস্করণটির চেয়ে সঠিকভাবে লেখার পক্ষে আরও শক্ত। এবং প্রচুর সি ++ বিকাশকারীরা কেবল ব্যতিক্রম-সুরক্ষাকে অবহেলা করে এবং তাদের ডোমেনের জন্য এটি ঠিক আছে তবে আমার ক্ষেত্রে আমি ব্যতিক্রমের ক্ষেত্রেও আমার কোডটি সঠিকভাবে কাজ করে তা নিশ্চিত করতে চাই (এমনকি পরীক্ষাগুলিও লিখতে পারে যেগুলি ব্যতিক্রমের পরীক্ষার জন্য ইচ্ছাকৃতভাবে ব্যতিক্রম ছুঁড়ে ফেলেছে) সুরক্ষা), এবং এটি এটি তোলে যাতে কোনও ফাংশন যদি কোনও কিছু ফেলে দেয় তবে কোনও ক্রিয়াকলাপটি অর্ধেক করে ফাংশনে ডেকে আনে এমন কোনও পার্শ্ব প্রতিক্রিয়াগুলি রোলব্যাক করতে সক্ষম হব।
আপনি যখন ব্যতিক্রম-নিরাপদ থাকতে চান এবং আপনার অ্যাপ্লিকেশনটি ক্রাশ এবং জ্বলিত না করে নিখুঁতভাবে ত্রুটিগুলি থেকে পুনরুদ্ধার করতে চান, তখন আপনাকে কোনও ত্রুটি / ব্যতিক্রম ঘটলে কোনও ক্রিয়াকলাপ ঘটাতে পারে এমন কোনও পার্শ্ব প্রতিক্রিয়াগুলি পূর্বাবস্থায়িত / পূর্বাবস্থায় ফিরিয়ে আনতে হবে। এবং সেখানে নির্মাতা আসলে কম্পিউটারের সময় সহ তার চেয়ে বেশি প্রোগ্রামার সময় বাঁচাতে পারে কারণ: ...
কোনও ফাংশনে পিছনে পার্শ্ব প্রতিক্রিয়াগুলি ঘূর্ণায়মান হওয়ার বিষয়ে আপনাকে চিন্তা করার দরকার নেই!
সুতরাং ফিরে মূল প্রশ্ন:
কোন পর্যায়ে অপরিবর্তনীয় শ্রেণি বোঝা হয়ে যায়?
এগুলি হ'ল ভাষাগুলির ক্ষেত্রে সর্বদা বোঝা যা অপরিবর্তনীয়তার চেয়ে পরিবর্তনের চারপাশে আরও ঘুরে বেড়ায়, এজন্য আমি মনে করি আপনারা সেগুলি ব্যবহার করা উচিত যেখানে সুবিধাগুলি উল্লেখযোগ্যভাবে ব্যয়কে ছাড়িয়ে যায়। তবে যথেষ্ট পরিমাণে বিশাল ডেটা স্ট্রাকচারের জন্য একটি বিস্তৃত পর্যায়ে, আমি বিশ্বাস করি যে এমন অনেকগুলি ক্ষেত্রে রয়েছে যেখানে এটি একটি উপযুক্ত বাণিজ্য-বন্ধ।
এছাড়াও খনিতে, আমার কাছে কেবল কয়েকটি অপরিবর্তনীয় ডেটা টাইপ রয়েছে এবং এগুলি বিশাল আকারের উপাদান (একটি চিত্র / টেক্সচারের পিক্সেল, একটি ইসিএসের সত্তা এবং উপাদানসমূহ, এবং শীর্ষগুলি / প্রান্ত / বহুভুজগুলি) সংরক্ষণ করার উদ্দেশ্যে নির্মিত সমস্ত বিশাল ডেটা স্ট্রাকচার're একটি জাল)।