بهبود خوانایی کد در بخش View با استفاده از قالب های برگشتی

سه شنبه 21 آذر 1402

قالب برگشتی یکی از ویژگی‌های جدیدی است که در آخرین نسخه چارچوب CodeBehind اضافه شده است. استفاده از این قابلیت، کدهای سمت سرور را به طور کامل از قسمت view جدا می کند.

بهبود خوانایی کد در بخش View با استفاده از قالب های برگشتی

مقدمه

تیم Elanat یکی از زیباترین ابتکارات در برنامه نویسی سال 2023 را با نام قالب برگشتی در فریم ورک CodeBehind، به عنوان یک ویژگی جدید اضافه کرده است. قالب برگشتی مفهوم تازه ای به الگوی برنامه نویسی Code-Behind می دهد. قبلا تلاش های بسیاری انجام شده بود تا بخش view تهی از کدنویسی سمت سرور باشد و برخی از بخش های تکرار شونده را خارج از بخش view قرار می دادند؛ جالب است که ایده انقالابی قالب برگشتی را همزمان در بخش view مشاهده خواهید کرد و همان جا می توانید ویرایش را انجام دهید و کنترل کاملی بر بخش view داشته باشید.

 

Code-Behind یک الگوی برنامه‌نویسی است که منطق ارائه را از کد HTML جدا می‌کند و امکان تفکیک بهتر منطق برنامه را فراهم می‌کند. این شامل ایجاد یک فایل کلاس جداگانه برای کد است که می تواند به قابلیت نگهداری و خوانایی کمک کند.

 

معمولاً افراد عادی Code-Behind را با فرم وب مایکروسافت می شناسند. لطفاً توجه داشته باشید که فریم ورک CodeBehind یک چارچوب بک-اند برای NET Core. است و ساختار آن هیچ ارتباطی با وب-فرم قبلی مایکروسافت ندارد.

 

فریم ورک CodeBehind متعلق به تیم Elanat می باشد و در سال 2023 معرفی شده است (بهتر است آن را Elanat CodeBehind framework بنامید).

 

نکته : هر جا در مقاله Code-Behind نوشتیم، منظور ما الگوی Code-Behind است و هر جا CodeBehind نوشتیم، منظور ما فریم ورک CodeBehind تیم Elanat می باشد. همچنین منظور از نحو نیز سینتکس می باشد.

لطفا توجه کنید که به دلیل تلفظ دور از نوع نوشته شدن، کلمه رازور را به صورت فارسی شده کلمه razor به کار برده ایم (کلمه razor چیزی بین ریزه و ریزا تلفظ می شود).

 

الگوی Code-Behind بخش طراحی (مانند html) را به طور کامل از بخش کدگذاری سمت سرور جدا می کند و توسعه دهندگان سمت سرور و سمت سرویس گیرنده بدون درگیر شدن در کار یکدیگر، توسعه را انجام می دهند.

 

مشکل حلقه ها و شرط ها

لطفاً توجه داشته باشید که مواردی مانند متغییرهای بین کد قطعه در بخش طراحی (html) همچنان مطابق با الگوی Code-Behind در نظر گرفته می شوند مگر اینکه کد قسمت سرور اضافه شود.

وجود متغیر بین کدهای html یا xml و ... کاملا قابل تشخیص است.

نمونه ای از متغیرهای بین قسمت طراحی

نحو رازور

<h1>@model.PageName</h1>

نحو استاندارد

<h1><%=model.PageName%></h1>

در دو مثال بالا، مقادیر model.PageName@ و <%model.PageName=%> به راحتی در تگ های html تشخیص داده می شوند، بنابراین الگوی Code-Behind هنوز در جای خود باقی است و طراحان یا توسعه دهندگان سمت کلاینت به راحتی می توانند منطق طراحی را مشاهده و درک کنند.

در اینجا مشکلی وجود نخواهد داشت و همچنان توسعه بر اساس الگوی Code-Behind است.

اما معمولاً برای موارد تکراری مانند حلقه ها و شرایط، یا باید کدهای قسمت طراحی را در کدهای سمت سرور اضافه کنید یا کدهای سمت سرور را در بخش طراحی اضافه کنید.

پس راه فراری نداری!

نمونه ای از کدنویسی سمت سرور در قسمت طراحی قرار دارد.

<table>
    <thead>
        <tr>
            <th>Column1</th>
            <th>Column2</th>
            <th>Column3</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>@item.Column1</td>
                <td>@item.Column2</td>
                <td>@item.Column3</td>
            </tr>
        }
    </tbody>
</table>

نمونه ای از ادغام قسمت طراحی در کدهای سمت سرور

model.ListValue = "<ul>";

foreach(string s in List)
    model.ListValue += "<li>" + s + "</li>";

model.ListValue += "</ul>";

استفاده از قالب برای انطباق با کد پشت

یکی از معروف ترین فریم ورک هایی که جداسازی کدهای سمت سرور از بخش طراحی را تضمین می کرد، وب-فرم مایکروسافت بود، اما این گارانتی هزینه سنگینی مانند کدهای اضافی و عدم کنترل کامل طراحان بر بخش طراحی داشت.

 

در حال حاضر، چارچوب CodeBehind از ساختار طراحی 100% مبتنی بر Code-Behind پشتیبانی می کند. این به لطف ویژگی جدید قالب برگشتی است که در آخرین نسخه این چارچوب اضافه شده است.

 

قالب ها بخش هایی از نمای صفحه هستند که قبل از کامپایل شدن بخش view به متغیرهای قالب متصل می شوند.

قالب برای نحو رازور و نحو استاندارد استفاده می شود. قالب های منطبق با نحو razor را نمی توان برای نحو استاندارد استفاده کرد. به همین ترتیب، قالب منطبق نحو استاندارد را نمی توان برای نحو تیغ استفاده کرد.

 

یک مثال ساده از قالب (نحو استاندارد).

<%@ Page Controller="YourProjectName.DefaultController" Model="YourProjectName.DefaultModel" %>
<!DOCTYPE html>
<html>
<head>
+   <#GlobalTags#>
    <title><%=model.PageTitle%></title>
</head>
<body>
    <%=model.BodyValue%>
</body>
</html>

+<#GlobalTags
+<meta charset="utf-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+<meta http-equiv="Content-Type" content="text/html; charset=utf-16" />
+<meta http-equiv="content-language" content="en">
+<script type="text/javascript" src="/client/script/global.js" ></script>
+<link rel="alternate" type="application/rss+xml" title="rss feed" href="/rss/" />
+<link rel="shortcut icon" href="/favicon.ico" />
+<link rel="stylesheet" type="text/css" href="/client/style/global.css" />
+#>

در این مثال، یک بخش قالب در متغیر  قالب فراخوانی می شود و خروجی به صورت زیر تبدیل می شود.

<%@ Page Controller="YourProjectName.DefaultController" Model="YourProjectName.DefaultModel" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-16" />
    <meta http-equiv="content-language" content="en">
    <script type="text/javascript" src="/client/script/global.js" ></script>
    <link rel="alternate" type="application/rss+xml" title="rss feed" href="/rss/" />
    <link rel="shortcut icon" href="/favicon.ico" />
    <link rel="stylesheet" type="text/css" href="/client/style/global.css" />
    <title><%=model.PageTitle%></title>
</head>
<body>
    <%=model.BodyValue%>
</body>
</html>

مثال بالا توانایی ساده قالب ها را در چارچوب CodeBehind نشان داد و شما را با مفهوم قالب ها آشنا کرد، اما قالب های برگشتی یک ویژگی منحصر به فرد دارند. قالب های برگشتی ابتدا در قالب درج می شوند و سپس کل قالب با قالب برگشتی جایگزین می شود.

 

دو نوع قالب وجود دارد:

1- قالب (یا بلاک قالب)

2- قالب بازگشت

 

هر دو نوع قالب را می توان با متغیر قالب فراخوانی کرد.

مثالی از تعریف قالب (نحو رازور).

+@#TemplateName{
@{
string ExampleText = "This is example text";
}
<b>Example value is : @ExampleText</b>
+}

در ابتدای تعریف هر قالب از علامت @ و # استفاده می شود و سپس نام قالب نوشته می شود و در پایان از کاراکتر بلاک ({) استفاده می شود. سپس مقادیر مورد نظر اضافه شده و در نهایت بلاک بسته می شود (}).

برای فراخوانی قالب باید متغیر قالب را بنویسید. برای نوشتن متغیر قالب، علامت و کاراکترهای رازور  (#@) در ابتدا اضافه می شود و سپس نام قالب نوشته می شود.

مثالی برای فراخوانی قالب با متغیر قالب.

<!DOCTYPE html>
<html>
<body>
+  @#TemplateName
</body>
</html>

مثال پس از چسباندن قالب (این کار به صورت موقت و قبل از مراحل کامپایل انجام می شود و شما تنها از نتیجه پاسخ صفحات متوجه این موضوع خواهید شد!).

<!DOCTYPE html>
<html>
<body>
@{
string ExampleText = "This is example text";
}
<b>Example value is : @ExampleText</b>
</body>
</html>

قالب های برگشتی ابتدا در متغیر همنام با نام قالب درج می شوند و سپس کل قالب با قالب برگشتی جایگزین می شود (هر سه نام یکسان هستند).

در ابتدای تعریف قالب برگشتی از علامت @ و # استفاده می شود و سپس نام قالب نوشته می شود. سپس کاراکتر مساوی (=) اضافه می شود و در پایان از کاراکتر بلاک ({) استفاده می شود. سپس مقادیر مورد نظر اضافه شده و در نهایت بلاک بسته می شود (}).

مثال (نحو رازور) قبل از چسباندن قالب، بخش view را مشاهده کنید.

<div class="header">
  <a href="#default">@model.Title</a>
  <div class="header-right">
    @#Tags={<a href="@#Href">@#PageName</a>}
  </div>
</div>

@#Tags{
@foreach (PageItem page in model.PageItemList)
{
    @#Tags
}
}

@#PageName{@page.Title}
@#Href{@(((page.Path == "main")? "/" : page.Path))}

چسباندن خودکار قالب مرحله اول

در کدهای بالا یک قالب برگشتی به نام Tags وجود دارد که با رشته =Tags#@ مشخص شده است و مقدار داخل آن نیز مشخص است.

<div class="header">
  <a href="#default">@model.Title</a>
  <div class="header-right">
    @#Tags={<a href="@#Href">@#PageName</a>}
  </div>
</div>

@#Tags{
@foreach (PageItem page in model.PageItemList)
{
    <a href="@#Href">@#PageName</a>
}
}

@#PageName{@page.Title}
@#Href{@(((page.Path == "main")? "/" : page.Path))}

همانطور که در کدهای بالا مشاهده می کنید. ابتدا مقدار داخل بلاک قالب برگشتی با نام Tags در متغیر قالب Tags در داخل بلاک قالب Tags جایگزین می شود.

 

چسباندن خودکار قالب مرحله دوم

<div class="header">
  <a href="#default">@model.Title</a>
  <div class="header-right">
    @foreach (PageItem page in model.PageItemList)
    {
        <a href="@#Href">@#PageName</a>
    }
  </div>
</div>

@#PageName{@page.Title}
@#Href{@(((page.Path == "main")? "/" : page.Path))}

با توجه به کدهای فوق در مرحله دوم مقادیر قالب Tags در محل قالب برگشتی جایگزین می شود.

چسباندن خودکار قالب مرحله سوم (سرانجام)

<div class="header">
  <a href="#default">@model.Title</a>
  <div class="header-right">
    @foreach (PageItem page in model.PageItemList)
    {
        <a href="@(((page.Path == "main")? "/" : page.Path))">@page.Title</a>
    }
  </div>
</div>

در مرحله آخر، مقادیر سایر قالب ها به جای متغیرهای قالب هم نام جایگزین می شوند.

 

در مثال قرار دادن قالب، اگر قالب را به صورت خارجی اضافه کنید، html زیر را در قسمت طراحی خواهید داشت.

نکته: در فریم ورک CodeBehind می توانید قالب را به صورت خارجی تعیین کنید. توضیح دادن این موضوع ما را از بحث قالب برگشتی منحرف می کند و درک مقاله را سخت می کند. برای اطلاعات بیشتر در مورد قالب ها می توانید به لینک ذیل مراجعه کنید:

https://github.com/elanatframework/Code_behind/blob/elanat_framework/doc/template.md

در زیر، بخش view را قبل از چسباندن قالب مشاهده کنید.

<div class="header">
  <a href="#default">@model.Title</a>
  <div class="header-right">
+    @#Tags={<a href="@#Href">@#PageName</a>}
  </div>
</div>

 

بدون قالب برگشتی، در بهترین حالت، html زیر را در قسمت طراحی خواهید داشت.

<div class="header">
  <a href="#default">@model.Title</a>
  <div class="header-right">
+ @foreach (PageItem page in model.PageItemList)
+ {
+    <a href="@(((page.Path == "main")? "/" : page.Path))">@page.Title</a>
+ }
  </div>
</div>

لطفاً توجه داشته باشید که این یک مثال ساده بود و ممکن است وضعیت بسیار پیچیده باشد.

 

شما علاوه بر نحو رازور همچنین می توانید از قالب ها برای نحو استاندارد استفاده کنید. کد زیر نمونه قالب قبلی را در نحو استاندارد نشان می دهد.

<div class="header">
  <a href="#default"><%=model.Title%></a>
  <div class="header-right">
    <#Tags=<a href="<#Href#>"><#PageName#></a>#>
  </div>
</div>

<#Tags
<% foreach (PageItem page in model.PageItemList)
{
    <#Tags#>
}
%>
#>

<#PageName <%=page.Title%>#>
<#Href <%=((page.Path == "main")? "/" : page.Path)%>#>

اگر مقدار برگشتی بین تگ های نحو استاندارد قرار گیرد، نحو، قبل از مقدار  برگشتی به طور خودکار بسته می شود و نحو بعد از آن باز می شود.

 

چسباندن مرحله آخر قالب در نحو استاندارد.

<div class="header">
  <a href="#default"><%=model.Title%></a>
  <div class="header-right">
    <% foreach (PageItem page in model.PageItemList)
    {
        %><a href="<%=((page.Path == "main")? "/" : page.Path)%>"><%=page.Title%></a><%
    }
    %>
  </div>
</div>

نتیجه گیری

مهم نیست چه مقدار سعی می کنید از ترکیب کدهای سمت سرور در بخش view اجتناب کنید، در برخی موارد مانند حلقه ها و شرایط، باید از کدهای سمت سرور در بخش view استفاده کنید. وجود درهم آمیزی کدهای سمت سرور و بخش طراحی (مثل html)، خوانایی کدها را کاهش می دهد و ظاهر بخش view را زشت می کند و حفظ کدها را دشوار می کند و همچنین منجر به تعامل پیچیده بین توسعه دهندگان سمت سرور و کلاینت در  برنامه های کاربردی در مقیاس بالا می شود. با اعمال قالب برگشتی، کد قسمت سرور خارج از بخش view باقی می ماند. در نتیجه بخش view ظاهر بسیار خوبی خواهد داشت و الگوی Code-Behind کاملا رعایت می شود.

پیوند ها

مخزن CodeBehind

https://github.com/elanatframework/Code_behind

دریافت فریم ورک CodeBehind از NuGet:

https://www.nuget.org/packages/CodeBehind

دریافت فریم ورک CodeBehind از GitHub:

https://github.com/elanatframework/Code_behind/releases

دریافت فریم ورک CodeBehind از وب سایت Elanat:

https://elanat.net/category/download_code_behind/

اشکان

نویسنده 3 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

تاکنون هیچ کاربری از این پست تشکر نکرده است

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید

نظرات کاربران

برای درج نظر باید وارد سایت شوید