Telescoping Constructor | تلسکوپینگ کانستراکتور
توضیحات جلسه
جزوه و مستندات
مفاهیم کلیدی
- Telescoping Constructor Pattern
الگویی برای ساخت objectهایی با پارامترهای متعدد است. در این الگو یک constructor فقط پارامترهای اجباری را دریافت میکند و constructorهای بعدی بهترتیب پارامترهای اختیاری بیشتری میپذیرند تا در نهایت تمام پارامترها پوشش داده شوند.
- Required Parameters
مقادیر ضروری برای ایجاد یک object معتبر هستند. در کلاس NutritionFacts، فیلدهای servingSize و servings پارامترهای اجباری محسوب میشوند.
- Optional Parameters
مقادیری هستند که تعیین آنها هنگام ساخت object الزامی نیست و میتوانند مقدار پیشفرض داشته باشند. فیلدهای calories، fat، sodium و carbohydrate در مثال، اختیاری هستند.
- Constructor Chaining
فراخوانی یک constructor از داخل constructor دیگر با استفاده از this(...) است. این روش منطق مقداردهی را در کاملترین constructor متمرکز کرده و از تکرار کد جلوگیری میکند.
- Default Value
مقداری است که در صورت تعییننشدن یک پارامتر اختیاری استفاده میشود. در مثال NutritionFacts، مقدار پیشفرض پارامترهای اختیاری برابر 0 در نظر گرفته شده است.
- Shortest Applicable Constructor
در الگوی telescoping constructor، کلاینت کوتاهترین constructorای را انتخاب میکند که تمام پارامترهای موردنیازش را پوشش دهد. بااینحال ممکن است برای رسیدن به یک پارامتر انتهایی، مجبور شود مقادیر پارامترهای اختیاری قبلی را نیز ارسال کند.
- Parameter Order Dependency
در constructorهای چندپارامتری، معنای هر مقدار به موقعیت آن وابسته است. بنابراین کلاینت باید ترتیب پارامترها را دقیقاً بداند و رعایت کند.
- Positional Arguments
آرگومانهایی هستند که معنا و مقصدشان فقط بر اساس موقعیت آنها در فراخوانی مشخص میشود. در کدی مانند new NutritionFacts(240, 8, 100, 0, 35, 27)، بدون مشاهدهی امضای constructor نمیتوان معنای هر عدد را بهسادگی تشخیص داد.
- Identically Typed Parameters
پارامترهای متوالی با نوع یکسان هستند. اگر چند پارامتر همگی از نوع int باشند، جابهجایی اشتباه آنها توسط compiler شناسایی نمیشود؛ زیرا امضای فراخوانی همچنان معتبر است.
- Client Code Readability
میزان قابلفهمبودن کدی است که از یک API استفاده میکند. constructorهای طولانی با آرگومانهای عددی متعدد، خوانایی کد کلاینت را کاهش میدهند.
- Scalability Problem
الگوی telescoping constructor برای تعداد کم پارامترها قابلاستفاده است، اما با افزایش پارامترهای اختیاری، تعداد constructorها و پیچیدگی استفاده از آنها بهسرعت افزایش مییابد.
- Immutable Object Initialization
در مثال، تمام فیلدها با final تعریف شدهاند و در زمان ساخت مقدار میگیرند. این طراحی امکان ایجاد object تغییرناپذیر را فراهم میکند، اما انتخاب روش مناسب برای ارسال پارامترهای متعدد اهمیت زیادی دارد.
موارد مصاحبه ای
- الگوی
Telescoping Constructorچیست؟
روشی است که در آن چند constructor با تعداد افزایشی از پارامترها تعریف میشوند؛ از پارامترهای اجباری شروع شده و به همهی پارامترهای اختیاری ختم میشوند.
- چرا
Telescoping Constructor Patternمقیاسپذیر نیست؟
زیرا با افزایش پارامترهای اختیاری، تعداد constructorها بیشتر میشود و نوشتن، خواندن و نگهداری کد دشوارتر خواهد شد.
Constructor Chainingچگونه انجام میشود؟
با استفاده از this(...)، یک constructor پارامترهای خود و مقادیر پیشفرض را به constructor کاملتر ارسال میکند.
- مزیت
Constructor Chainingچیست؟
منطق مقداردهی فیلدها را در یک محل متمرکز میکند، تکرار کد را کاهش میدهد و تغییر مقادیر پیشفرض را سادهتر میسازد.
- مشکل اصلی فراخوانی
constructorهای طولانی چیست؟
معنای آرگومانها از روی فراخوانی مشخص نیست و برنامهنویس باید ترتیب و تعداد پارامترها را با دقت بررسی کند.
- چرا جابهجایی دو پارامتر همنوع خطرناک است؟
اگر دو پارامتر هر دو از یک نوع مانند int باشند، compiler جابهجایی آنها را تشخیص نمیدهد؛ اما مقادیر در فیلدهای اشتباه قرار میگیرند و برنامه هنگام اجرا رفتار نادرست خواهد داشت.
- آیا استفاده از مقدار پیشفرض مشکل
Telescoping Constructorرا کاملاً حل میکند؟
خیر. برای تنظیم یک پارامتر انتهایی ممکن است کلاینت مجبور شود برای پارامترهای اختیاری قبلی نیز مقادیر پیشفرض را بهصورت دستی ارسال کند.
- تفاوت پارامتر اجباری و اختیاری چیست؟
پارامتر اجباری برای ساخت یک object معتبر ضروری است، اما پارامتر اختیاری میتواند تعیین نشود و مقدار پیشفرض دریافت کند.
- چرا استفادهی گسترده از پارامترهای
intدر یکconstructorنامناسب است؟
زیرا همهی آرگومانها از نظر نوع یکساناند و compiler نمیتواند خطاهای معنایی ناشی از جابهجایی آنها را تشخیص دهد.
- چه زمانی
Telescoping Constructorقابلقبول است؟
زمانی که تعداد پارامترها کم، ترتیب آنها واضح و احتمال افزایش پارامترهای اختیاری در آینده پایین باشد.
سناریو کاربردی
- تعریف اطلاعات تغذیهای محصول
کلاس NutritionFacts شامل دو فیلد اجباری و چهار فیلد اختیاری است:
servingSize: اندازهی هر وعدهservings: تعداد وعدهها در بستهcalories: کالری هر وعدهfat: چربی هر وعدهsodium: سدیم هر وعدهcarbohydrate: کربوهیدرات هر وعده
برای پشتیبانی از ترکیبهای مختلف پارامترها، چند constructor تعریف میشود. هر constructor با استفاده از this(...)، پارامترهای موجود و مقدار پیشفرض 0 را به constructor بعدی ارسال میکند. کاملترین constructor تمام فیلدها را مقداردهی میکند.
- ساخت نمونه برای محصول
NutritionFacts cocaCola =
new NutritionFacts(240, 8, 100, 0, 35, 27);
این فراخوانی بهترتیب، اندازهی وعده، تعداد وعدهها، کالری، چربی، سدیم و کربوهیدرات را تعیین میکند.
- مشکل خوانایی
از روی مقادیر 240، 8، 100، 0، 35 و 27 نمیتوان بدون مراجعه به امضای constructor تشخیص داد که هر عدد متعلق به کدام ویژگی است. کلاینت باید پارامترها را بشمارد و ترتیب آنها را به خاطر بسپارد.
- مشکل پارامترهای ناخواسته
اگر کلاینت بخواهد sodium و carbohydrate را تعیین کند ولی تمایلی به تعیین fat نداشته باشد، همچنان باید مقدار پیشفرض 0 را برای fat ارسال کند.
- خطر خطای زمان اجرا
اگر کلاینت دو آرگومان int مانند sodium و carbohydrate را جابهجا کند، کد بدون خطای compile-time کامپایل میشود؛ اما اطلاعات تغذیهای اشتباه ثبت خواهد شد.
بیشتر بدانید
- نکتهی طراحی API
از تعریف constructorهایی با تعداد زیاد پارامتر، بهویژه پارامترهای همنوع، خودداری کنید؛ زیرا احتمال استفادهی اشتباه از API را افزایش میدهد.
- نکتهی خوانایی
فراخوانی زیر از نظر نحوی معتبر است، اما معنای آرگومانها را منتقل نمیکند:
new NutritionFacts(240, 8, 100, 0, 35, 27);
هرچه تعداد مقادیر بیشتر باشد، بررسی و نگهداری این کد دشوارتر میشود.
- نکتهی مقدار پیشفرض
مقادیر پیشفرض باید در یک نقطه، ترجیحاً کاملترین constructor یا مکانیزم ساخت مرکزی، مدیریت شوند تا از ناسازگاری جلوگیری شود.
- نکتهی جایگزین
برای کلاسهایی با پارامترهای اجباری و اختیاری متعدد، الگوی Builder معمولاً گزینهای خواناتر و ایمنتر از Telescoping Constructor Pattern است.
- نکتهی اعتبارسنجی
متمرکزکردن مقداردهی در کاملترین constructor امکان انجام validation یکپارچه را فراهم میکند؛ مانند جلوگیری از مقدار منفی برای calories یا sodium.
- نکتهی خطای معنایی
compiler فقط سازگاری نوعها را بررسی میکند و معنای مقادیر را نمیداند. بنابراین دو آرگومان همنوع ممکن است بدون خطای کامپایل جابهجا شوند و یک logic bug ایجاد کنند.
