হাসিব, চলো তোমার কোর্সের ৯২ নম্বর লেকচারটি নিয়ে বিস্তারিত আলোচনা করি। আউটলাইন অনুযায়ী এটি (Section 8: Views - MVC Architecture Pattern) এর অংশ, যার শিরোনাম “Local Functions”। এই লেকচারে Razor View-এর ভেতরে কীভাবে C# এর Local Function এবং @functions ব্লক ব্যবহার করে Reusable code তৈরি করা যায়, তা নিয়ে আলোচনা করা হয়েছে।
নিচে পুরো লেকচারটির বিস্তারিত ব্রেকডাউন দেওয়া হলো:
📝 Summary (সারসংক্ষেপ)
- Topic: Razor Views-এ Local Functions এবং @functions ব্লকের ব্যবহার।
- Core Purpose: একই View-এর ভেতরে বারবার ব্যবহার করা যায় এমন C# লজিক বা ক্যালকুলেশনকে একটি ফাংশনের ভেতরে আবদ্ধ করে Reusability বাড়ানো।
- Local Functions: @ { … } ব্লকের ভেতরে সাধারণ C# মেথডের মতোই তৈরি করা হয়।
- @functions Block: এর মাধ্যমে Razor View-কে একটি ক্লাসের মতো ট্রিট করে তার ভেতরে Method, Property এবং Field তৈরি করা যায়।
- Architecture Note: Razor View-তে অনেক বেশি C# কোড বা লজিক লেখা MVC প্যাটার্নের পরিপন্থী। তাই এটি খুব রেয়ার কেসে (Rare cases) ব্যবহার করা হয়।
📌 Introduction to Local Functions in Razor [Priority: 8/10]
C# 7.0-এ Local Functions এর কনসেপ্ট প্রথম আসে, যেখানে একটি মেথডের ভেতরে আরেকটি মেথড তৈরি করা যায়। Razor View-তেও এই কনসেপ্ট সাপোর্ট করে।
Why use it? (কেন ব্যবহার করবো?) ধরে নাও, তোমার View-তে একটি foreach লুপ চলছে। লুপের ভেতরে ইউজারের Date of Birth (DoB) থেকে তার বর্তমান বয়স (Age) হিসাব করতে হবে। এখন এই বয়স বের করার লজিকটা যদি তুমি লুপের ভেতরেই লেখো, তাহলে কোড অনেক বড় এবং হিজিবিজি হয়ে যাবে। এর বদলে তুমি View-এর উপরের দিকে একটি ছোট্ট Local function বানিয়ে নিতে পারো, যা Date of Birth ইনপুট হিসেবে নিবে এবং Age রিটার্ন করবে।
🛠️ Code Implementation: Local Function
@{
// এটি একটি Local Function যা View এর ভেতরেই ডিফাইন করা হয়েছে
double? GetAge(DateTime? dateOfBirth)
{
if (dateOfBirth is not null)
{
// বর্তমান সময় থেকে জন্মতারিখ বিয়োগ করে দিন বের করা হচ্ছে
var span = DateTime.Now - dateOfBirth.Value;
// দিনকে ৩৬৫ দিয়ে ভাগ করে এবং Round করে বছর বের করা হচ্ছে
return Math.Round(span.TotalDays / 365.25);
}
return null;
}
// ডেমো ডেটা
List<Person> people = new List<Person>
{
new Person { Name = "Hasib", DateOfBirth = new DateTime(2000, 1, 1) },
new Person { Name = "John", DateOfBirth = null }
};
}
<h3>User List</h3>
@foreach (var person in people)
{
<div>
<span>Name: @person.Name</span> <br />
@* Local Function টি কল করে বয়স প্রিন্ট করা হচ্ছে *@
@if (person.DateOfBirth != null)
{
<span>Age: @GetAge(person.DateOfBirth) years old</span>
}
</div>
}
কিভাবে কাজ করছে?
- @ { … } ব্লকের ভেতরে GetAge নামক একটি ফাংশন তৈরি করা হয়েছে।
- ফাংশনটি একটি DateTime? প্যারামিটার নেয় এবং ক্যালকুলেশন শেষে একটি double? রিটার্ন করে।
- নিচে HTML রেন্ডার করার সময় @GetAge(person.DateOfBirth) লিখে ফাংশনটিকে কল করা হয়েছে।
📌 The @functions Block in Razor [Priority: 6/10]
লেকচারের দ্বিতীয়াংশে ইনস্ট্রাক্টর @functions ব্লক সম্পর্কে বলেছেন।
Background Theory: তুমি যখন একটি .cshtml ফাইল সেভ করো, তখন রানটাইমে ASP.NET Core ওই ফাইলটিকে কম্পাইল করে একটি C# Class-এ রূপান্তর করে (যা RazorPage নামক বেস ক্লাস থেকে ইনহেরিট হয়)।
যেহেতু এটি দিনশেষে একটি ক্লাস, তাই তুমি চাইলে এর ভেতরে Method, Property এবং Field (Variable) তৈরি করতে পারো। আর এই কাজটি করার জন্যই @functions ব্লক ব্যবহার করা হয়।
🛠️ Code Implementation: @functions
@functions {
// 1. Field
private string _defaultGreeting = "Welcome to our site";
// 2. Property
public string AppVersion { get; set; } = "v1.0.5";
// 3. Method (এটি আর Local Function নেই, এটি এখন ক্লাসের মেথড)
public double? CalculateAge(DateTime? dob)
{
if(dob.HasValue)
{
return Math.Round((DateTime.Now - dob.Value).TotalDays / 365.25);
}
return null;
}
}
<div>
<!-- Property এবং Field এক্সেস করা হচ্ছে -->
<p>@_defaultGreeting. System is running on @AppVersion</p>
</div>
Local Function বনাম @functions এর পার্থক্য:
- @{ … } এর ভেতরে লেখা ফাংশনগুলো হলো Local Functions।
- @functions { … } এর ভেতরে লেখা ফাংশনগুলো হলো কম্পাইল হওয়া ভিউ ক্লাসের Regular Methods।
Limitations: এই ফাংশন, ফিল্ড বা প্রোপার্টিগুলো শুধুমাত্র এই নির্দিষ্ট View (Index.cshtml)-এর ভেতরেই ব্যবহার করা যাবে। অন্য কোনো View থেকে এদের কল করা যাবে না।
⭐ Best Practices & MVC Architecture Note [Priority: 10/10]
ইনস্ট্রাক্টর লেকচারের শেষে একটি খুবই গুরুত্বপূর্ণ কথা বলেছেন, যা তোমার সফটওয়্যার ইঞ্জিনিয়ারিং ক্যারিয়ারের জন্য ক্রুশিয়াল:
“In general, views are not intended to have much amount of C-sharp code… Everything should be supplied by the controller.”
- Keep Views Clean (Thin View, Fat Controller): MVC আর্কিটেকচারের মূল নিয়ম হলো View এর কাজ শুধুমাত্র ডেটা প্রেজেন্ট করা (HTML/UI)। View-তে কোনো ধরনের বিজনেস লজিক, ক্যালকুলেশন (যেমন বয়স বের করা) বা ডেটা ম্যানিপুলেশন থাকা উচিত নয়।
- Where to put the logic?: বয়স (Age) বের করার লজিকটি View-তে না লিখে তোমার Person Model ক্লাসে একটি Read-only Property হিসেবে লেখা উচিত, অথবা Controller থেকে ক্যালকুলেট করে View-তে পাঠানো উচিত।
Modern MVC Approach (How it should be done):
Model Class:
public class Person
{
public string Name { get; set; }
public DateTime? DateOfBirth { get; set; }
// Model এর ভেতরেই Age ক্যালকুলেশন রাখা সবচেয়ে স্মার্ট কাজ
public int? Age
{
get
{
if (!DateOfBirth.HasValue) return null;
var today = DateTime.Today;
var age = today.Year - DateOfBirth.Value.Year;
// লিপ ইয়ার বা জন্মদিনের আগের ডেট হ্যান্ডেল করা
if (DateOfBirth.Value.Date > today.AddYears(-age)) age--;
return age;
}
}
}
View (.cshtml):
@foreach (var person in Model)
{
<div>
<span>Name: @person.Name</span>
@if (person.Age.HasValue)
{
<span>Age: @person.Age years old</span>
}
</div>
}
দেখো, View এখন কত ক্লিন! View-তে আর কোনো মেথড বা ক্যালকুলেশন নেই। রিয়েল-ওয়ার্ল্ড প্রজেক্টে এভাবেই কাজ করা হয়। @functions বা View-তে Local function এর ব্যবহার খুব রেয়ার এবং এগুলো এড়িয়ে চলাই ভালো।