چندمدلسازی دامنه‌محور

این مقاله در حال ترجمه از ویکی انگلیسی است
لطفا حذف نشود.

مدل‌سازی چندوجهی خاص دامنه یک پارادایم توسعه نرم‌افزار است که در آن هر دیدگاه به‌طور صریح به‌عنوان یک زبان خاص دامنه (DSL) جداگانه بیان می‌شود.

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

مدل‌سازی چندوجهی خاص دامنه زمانی امیدوارکننده است که با پارادایم‌های توسعه سنتی مانند برنامه‌نویسی با یک زبان واحد و مدل‌سازی چندمنظوره مقایسه شود. برای بهره‌برداری از مزایای این پارادایم جدید، باید مشکل هماهنگی را حل کرد. این مشکل همچنین به‌عنوان مشکل پراکندگی در زمینه مدیریت مدل‌های جهانی شناخته می‌شود.

یک پیشنهاد برای حل این مشکل، روش هماهنگی است. این یک روش سه مرحله‌ای است که برای غلبه بر موانع یکپارچه‌سازی دیدگاه‌های مختلف و هماهنگی زبان‌های مختلف ارائه شده است. این روش نحوه (1) شناسایی و (2) مشخص کردن ارجاعات میان مرزهای زبان‌ها، یعنی همپوشانی‌های بین زبان‌های مختلف را تجویز می‌کند. در نهایت، این روش پیشنهاد های مشخصی برای (3) اعمال این دانش در توسعه واقعی در قالب انطباق، ناوبری و راهنمایی ارائه می‌دهد.

**مثال تشویقی**

سیستم‌های سازمانی مبتنی بر زبان‌های خاص دامنه متعدد بسیار رایج هستند. زبان‌هایی که متامدل آن‌ها در زبان نشانه‌گذاری قابل گسترش (XML) تعریف شده است، به‌ویژه در حال گسترش هستند. برای نشان دادن توسعه با زبان‌های متعدد، از یک مطالعه موردی استفاده می‌کنیم: سیستم Apache Open For Business (OFBiz). به طور خلاصه، OFBiz یک سیستم برنامه‌ریزی منابع سازمانی است که شامل اجزای استاندارد مانند موجودی، حسابداری، تجارت الکترونیک و غیره است. این اجزا با ترکیبی از زبان‌های مبتنی بر XML و کدهای جاوا معمولی پیاده‌سازی شده‌اند. به عنوان یک مثال، ما بر روی بخش مدیریت محتوا تمرکز می‌کنیم، به‌ویژه یک مورد استفاده که در آن کاربر مدیریتی یک نظرسنجی آنلاین ایجاد می‌کند، همانطور که در اسکرین‌شات زیر نشان داده شده است. این مثال را "مثال ایجاد نظرسنجی" می‌نامیم. شکل یک اسکرین‌شات از رابط کاربری مدیریتی برنامه مدیریت محتوا در یک نمونه OFBiz در حال اجرا را نشان می‌دهد. برای ایجاد یک نظرسنجی، کاربر فیلدهای فرم ورودی را پر کرده و دکمه به‌روزرسانی را فشار می‌دهد. این عمل یک نظرسنجی جدید ایجاد می‌کند که می‌توان آن را ویرایش کرده و در نهایت در وب‌سایت جلویی OFBiz منتشر کرد. در پشت صحنه، این مورد استفاده شامل چندین آثار نوشته شده در زبان‌های مختلف است. در این مثال، ما تنها به سه زبان از این زبان‌ها تمرکز می‌کنیم: زبان Entity، زبان Service و زبان Form.

این سه زبان به طور تقریبی به ترتیب به مدل ساختاری، رفتار برنامه و نگرانی رابط کاربری در OFBiz اشاره دارند. زبان Entity برای توصیف مدل داده زیربنایی استفاده می‌شود و در نتیجه نحوه ذخیره‌سازی نظرسنجی ایجاد شده را تعیین می‌کند. زبان Service برای توصیف رابط سرویسی که وقتی کاربر دکمه به‌روزرسانی را فشار می‌دهد، فراخوانی می‌شود، استفاده می‌شود. در نهایت، زبان Form برای توصیف ظاهر بصری فرم استفاده می‌شود. اگرچه این سه زبان برای چیزهای مختلف طراحی شده‌اند، اما نمی‌توان آن‌ها را به‌طور کامل از هم جدا کرد. رابط کاربری منطق خاصی از برنامه را فراخوانی می‌کند و این منطق برنامه داده‌های برنامه را دستکاری می‌کند. این مثال از نگرانی‌های غیر اورتوگونال است. زبان‌ها همپوشانی دارند زیرا نگرانی‌هایی که نمایندگی می‌کنند نمی‌توانند به طور کامل از هم جدا شوند. اکنون این سه زبان را به صورت پایین به بالا بررسی کرده و همپوشانی‌های آن‌ها را توضیح می‌دهیم.

**Entity DSL**

زبان Entity DSL ساختار داده‌ها را در OFBiz تعریف می‌کند. فهرست زیر تعریف موجودیت Survey را نشان می‌دهد که شیء تجاری است که نمایانگر مفهوم یک نظرسنجی است. کد در فهرست به وضوح قابل فهم است: موجودیتی به نام Survey با 10 فیلد تعریف شده است. هر فیلد یک نام و نوع دارد. فیلد surveyId به عنوان کلید اصلی استفاده می‌شود. این تعریف توسط یک مؤلفه مرکزی در OFBiz به نام entity engine بارگذاری می‌شود. entity engine یک شیء تجاری متناظر را نمونه‌سازی می‌کند. هدف entity engine مدیریت ویژگی‌های تراکنشی تمام اشیاء تجاری و تعامل با مکانیزم‌های مختلف پایداری مانند Java Database Connectivity، Enterprise JavaBeans یا حتی برخی از سیستم‌های قدیمی است.


```
<entity entity-name="Survey" ... title="Survey Entity">
    <field name="surveyId" type="id-ne"/>
    <field name="surveyName" type="name"/>
    <field name="description" type="description"/>
    <field name="comments" type="comment"/>
    <field name="submitCaption" type="short-varchar"/>
    <field name="responseService" type="long-varchar"/>
    <field name="isAnonymous" type="indicator" .../>
    <field name="allowMultiple" type="indicator" .../>
    <field name="allowUpdate" type="indicator" .../>
    <field name="acroFormContentId" type="id-ne" .../>
    <prim-key field="surveyId"/>
  </entity>
```


**Service DSL**

زبان Service DSL رابط خدمات در OFBiz را مشخص می‌کند. هر سرویس بخشی از منطق برنامه سیستم را در بر می‌گیرد. هدف این زبان داشتن یک انتزاع یکنواخت از مکانیزم‌های مختلف پیاده‌سازی است. سرویس‌های فردی می‌توانند به زبان جاوا، یک زبان اسکریپتی یا با استفاده از یک موتور قواعد پیاده‌سازی شوند. فهرست زیر رابط سرویس createSurvey را نشان می‌دهد.

علاوه بر نام، عنصر سرویس مکان و دستور فراخوانی پیاده‌سازی این سرویس را مشخص می‌کند. ویژگی default-entity-name مشخص می‌کند که این سرویس به موجودیت Survey اشاره دارد که در فهرست قبلی تعریف شده است. این یک همپوشانی بین دو زبان است، به‌ویژه آنچه به نام ارجاع نرم گفته می‌شود. یک مدل در Service DSL به یک مدل در Entity DSL اشاره دارد. این ارجاع در دو عنصر auto-attributes زیر استفاده می‌شود که ورودی و خروجی سرویس را به صورت ویژگی‌های تایپ‌شده مشخص می‌کنند. به عنوان ورودی، سرویس ویژگی‌هایی را می‌پذیرد که مربوط به تمام فیلدهای غیرکلید اصلی (nonpk) موجودیت Survey هستند و این ویژگی‌ها اختیاری هستند. به عنوان خروجی، سرویس ویژگی‌هایی را که مربوط به فیلدهای کلید اصلی (pk) موجودیت Survey هستند، یعنی در این مورد فیلد surveyId، باز می‌گرداند و این ویژگی‌ها اجباری هستند. هدف ارجاع میان زبان‌ها در اینجا کاهش تکرار است. ویژگی‌های سرویس createSurvey به فیلدهای موجودیت Survey مربوط می‌شوند و بنابراین تنها لازم است یک بار آن‌ها را مشخص کنیم.


```
<service name="createSurvey" default-entity-name="Survey" ...
           location="org/ofbiz/content/survey/SurveyServices.xml"
           invoke="createSurvey"> ...
    <permission-service service-name="contentManagerPermission"
                        main-action="CREATE"/>
    <auto-attributes include="nonpk" mode="IN" optional="true"/>
    <auto-attributes include="pk" mode="OUT" optional="false"/>
  </service>
```


**Form DSL**

زبان Form DSL برای توصیف چیدمان و ظاهر بصری فرم‌های ورودی در رابط کاربری استفاده می‌شود. این زبان از مفاهیم دامنه‌ای مانند Form و Field تشکیل شده است. فهرست زیر پیاده‌سازی فرم EditSurvey را نشان می‌دهد. این بار زبان Form DSL با زبان Service DSL همپوشانی دارد. ویژگی target فرم و عناصر alt-target مشخص می‌کنند که ورودی از ارسال این فرم باید به سرویس‌های updateSurvey یا createSurvey هدایت شود. عنصر auto-fields-service مشخص می‌کند که فرم باید شامل فیلدی باشد که به هر یک از ویژگی‌های سرویس updateSurvey (که مشابه ویژگی‌های سرویس createSurvey هستند) مربوط باشد. این اثر مشابهی از وارد کردن تعاریف از یک مدل دیگر را تولید می‌کند، همانطور که در مورد عناصر auto-attributes در فهرست قبلی ذکر شد. در پایین‌تر، می‌بینیم که می‌توان ظاهر این فیلدهای وارد شده مانند isAnonymous را سفارشی کرد. در نهایت، یک submitButton با عنوان محلی‌سازی شده اضافه می‌شود تا کاربر بتواند داده‌های خود را به سرویس ارجاع‌شده ارسال کند.


```
<form name="EditSurvey" type="single" target="updateSurvey"
        title="" default-map-name="survey">
    <alt-target use-when="survey==null" target="createSurvey"/>
    <auto-fields-service service-name="updateSurvey"/>
    <field use-when="survey!=null" name="surveyId" ... />
    ...
    <field name="isAnonymous">
      <drop-down no-current-selected-key="N" allow-empty="false">
        <option key="Y"/><option key="N"/>
      </drop-down>
    </field>
    ...
    <field name="submitButton" title="${uiLabelMap.CommonUpdate}"
           widget-style="smallSubmit">
      <submit button-type="button"/>
    </field>
  </form>
```


مثال ایجاد نظرسنجی که در اینجا توصیف شده است با استفاده از مدل‌هایی در سه زبان مختلف پیاده‌سازی شده است. پیاده‌سازی کامل در واقع شامل زبان‌های بیشتری مانند Screen DSL برای مشخص کردن چیدمان صفحه‌ای است که فرم در آن قرار می‌گیرد و Minilang DSL که یک زبان دستکاری داده‌ها است که برای پیاده‌سازی سرویس استفاده می‌شود. با این حال، این سه زبان ایده اصلی ساختن هر نگرانی به صورت ملموس را نشان می‌دهند. این مثال همچنین یک روش ساده برای کاهش تکرار با اجازه دادن به همپوشانی جزئی زبان‌ها را نشان می‌دهد.

**Multi-level customization**

زبان‌های خاص دامنه‌ای مانند زبان‌های توصیف‌شده در بالا، بیان‌گری محدودی دارند. اغلب لازم است که قطعه‌کدهایی به زبان‌های عمومی مانند جاوا اضافه شوند تا عملکردهای خاصی که فراتر از دامنه زبان‌ها هستند پیاده‌سازی شوند. این روش را سفارشی‌سازی چندسطحی می‌نامند. از آنجا که این روش در تنظیمات با زبان‌های متعدد به‌طور رایج استفاده می‌شود، آن را با ادامه مثال توضیح خواهیم داد. بیایید این مثال را "مثال ساخت PDF" بنامیم.

فرض کنید می‌خواهیم یک فایل PDF برای هر پاسخ نظرسنجی به نظرسنجی‌های آنلاین که کاربران ایجاد می‌کنند بسازیم. ساخت فایل PDF خارج از دامنه زبان‌های ما است، بنابراین باید کد جاوا بنویسیم که بتواند یک کتابخانه PDF شخص ثالث را فراخوانی کند تا این عملکرد خاص را انجام دهد. دو اثر لازم است:

اولاً، یک مدل سرویس اضافی که در زیر آمده است، در Service DSL که رابط سرویس خاص را تعریف می‌کند تا بتوان آن را در سطح مدل دسترسی کرد. مدل سرویس مکان پیاده‌سازی و ویژگی‌های ورودی و خروجی را توصیف می‌کند.


```
<service name="buildPdfFromSurveyResponse" engine="java"
    location="org.ofbiz.content.survey.PdfSurveyServices"
    invoke="buildPdfFromSurveyResponse">
    <attribute name="surveyResponseId" mode="IN"
      optional="false" .../>
    <attribute name="outByteWrapper" mode="OUT"
      optional="false" .../>
  </service>
```


ثانیاً، به یک قطعه‌کد نیاز داریم که در زیر آمده است، که شامل پیاده‌سازی واقعی این سرویس است. یک سرویس می‌تواند ورودی‌ها و خروجی‌های متعددی داشته باشد، بنابراین ورودی به متد جاوا یک نقشه است، که به آن context می‌گویند، از نام‌های آرگومان به مقادیر آرگومان و خروجی را به صورت یک نقشه دیگر به نام results برمی‌گرداند.


```
public static Map buildPdfFromSurveyResponse
  (DispatchContext dctx , Map context) {
    String id = (String) context.get("surveyResponseId");
    Map results = new HashMap();
    try {
      // ...the response is retrieved from the database...
      // ...a pdf is built from the response...
      // ...the pdf is serialized as a bytearray...
    ByteWrapper outByteWrapper = ...;
    results.put("outByteWrapper",outByteWrapper );
    } catch (Exception e) {}
    return results;
  }
```


این روش سفارشی‌سازی چندسطحی از ارجاعات نرم مشابه مثال ایجاد نظرسنجی استفاده می‌کند. تفاوت اصلی این است که ارجاع در اینجا بین مدل و کد است نه بین مدل‌ها. مزیت در این مورد این است که می‌توان از یک کتابخانه جاوای شخص ثالث برای ساخت PDF بهره برد. یک کاربرد معمول دیگر این است که از قطعه‌کدهای جاوا برای فراخوانی وب‌سرویس‌های خارجی استفاده شده و نتایج را در قالب مناسب وارد کنیم.

**مشکل هماهنگی**

این مثال برخی از مزایای استفاده از زبان‌های مختلف در توسعه را نشان می‌دهد. با این حال، مشکلاتی نیز با این نوع توسعه همراه است. این مشکلات ناشی از این است که هرچه تعداد بیشتری از مصنوعات را وارد فرآیند خود کنیم، نیاز به هماهنگی بیشتر بین تلاش‌های توسعه‌دهنده داریم. ما این مشکلات را به‌عنوان مشکل هماهنگی ارجاع خواهیم داد. مشکل هماهنگی جنبه مفهومی و فنی دارد. از نظر مفهومی، مشکل اصلی این است که زبان‌های مختلف و تعامل آنها را درک کنیم. برای طراحی و هماهنگی صحیح مدل‌ها در زبان‌های مختلف، توسعه‌دهندگان باید درک کافی از نحوه تعامل زبان‌ها داشته باشند. از نظر فنی، مشکل اصلی این است که انطباق را اعمال کنیم. ابزارها باید برای شناسایی ناسازگاری‌ها در زمان مدل‌سازی و کمک به توسعه‌دهندگان برای حل این ناسازگاری‌ها فراهم شوند. در ادامه، این دو جنبه را با جزئیات بیشتری بررسی خواهیم کرد.

**هماهنگی به‌عنوان یک چالش مفهومی**

اولین مشکلی که توسعه‌دهندگان هنگام شروع به توسعه با زبان‌های مختلف با آن روبه‌رو می‌شوند، کافوفونی زبان‌ها است. یادگیری زبان‌های مختلف و درک تعامل آنها برای درک ترکیب پیچیده مصنوعات ضروری است. به‌عنوان مثال، فریم‌ورک OFBiz هفده زبان مختلف دارد و بیش از 200,000 خط کد زبان خاص دامنه، بنابراین پیچیدگی می‌تواند بسیار زیاد باشد! در حال حاضر هیچ روش شناخته‌شده‌ای برای مشخص کردن زبان‌های مختلف وجود ندارد که توسعه‌دهندگان بتوانند به سرعت به درک عملیاتی دست یابند. ابزارها در اینجا به‌عنوان یک مکانیزم خودجوش برای یادگیری و کاوش اهمیت دارند زیرا توسعه‌دهندگان معمولاً از ابزارها برای یادگیری از طریق آزمایش‌ها استفاده می‌کنند. به‌ویژه سه زمینه وجود دارد که ابزارها برای مدل‌های خاص دامنه مفید هستند:

1. درک یک زبان

2. درک تعامل زبان‌ها

3. درک نحوه استفاده از زبان‌ها

اولاً، درک یک زبان می‌تواند دشوار باشد و در مورد زبان‌های خاص دامنه مبتنی بر XML، یک اعتراض رایج و شهودی این است که «نحو اهمیت دارد». این استدلال می‌تواند به‌صورت زیر بیان شود: «زبان‌های مختلف سخت به‌فهم هستند و تنها باعث سردرگمی می‌شوند زیرا نحو مبتنی بر XML آن‌ها به‌ویژه پرجزئیات و غیرقابل‌فهم است. استفاده از یک زبان عمومی مانند جاوا بهتر خواهد بود زیرا در آن صورت توسعه‌دهندگان می‌توانند از نحو‌ای که قبلاً می‌شناسند استفاده کنند». در حالی که این اعتراض قطعاً مهم است، اما نکته مرکزی را از دست می‌دهد. XML یا یک فرمت مشابه ممکن است نحوی نباشد که توسعه‌دهندگان در واقع با آن کار می‌کنند. یکی از مزایای استفاده از زبان‌های خاص دامنه مبتنی بر XML این است که می‌توانیم ویرایشگرهای خاص دامنه ارائه دهیم. شکل زیر نشان می‌دهد که یک ویرایشگر فرضی برای Entity DSL چگونه ممکن است به نظر برسد. این ویرایشگر دامنه را به‌صورت ساده و جذاب بصری ارائه می‌دهد اما ممکن است از نمایش XML (و شاید یک پیکربندی طراحی) در پشت‌صحنه استفاده کند.

دقیقاً همان‌طور که ممکن است شکایت کنیم که XML انتخاب بدی است، می‌توانیم اعتراض کنیم که زبان عمومی مانند جاوا برای برخی از وظایف انتخاب بدی است. علاوه بر این، توسعه‌دهندگان ممکن است کمتر از ویرایشگر در شکل نسبت به کد XML یا جاوا ترس داشته باشند. اگر قبول کنیم که نحو اهمیت دارد، استفاده از زبان‌های مختلف با ویرایشگرهای اختصاصی یک استراتژی منطقی می‌شود. سادگی ویرایشگر باعث می‌شود که زبان آسان‌تر درک شود و بنابراین راحت‌تر استفاده شود. به عبارت دیگر، اعتراض به اهمیت نحو ممکن است دقیقاً دلیلی باشد که ما به‌دنبال کاوش در زمینه زبان‌های خاص دامنه هستیم.

ثانیاً، تعاملات زبان‌ها روابط بین زبان‌ها را آشکار می‌کند. توسعه‌دهندگان باید قادر باشند بین عناصر مرتبط در مصنوعات مختلف جابجا شوند. سهولت ناوبری بین مصنوعات مختلف نرم‌افزاری یک معیار مهم برای ابزارها در محیط‌های توسعه سنتی است. اگرچه در این زمینه مطالعات تجربی انجام نداده‌ایم، اما فرض می‌کنیم که تسهیلات ناوبری مناسب بهره‌وری را افزایش می‌دهد. این ادعا با مشاهده‌ای که در حال حاضر تمام محیط‌های توسعه اصلی امکانات ناوبری پیشرفته‌ای مانند مرورگر سلسله‌مراتب نوع یا توانایی جستجو و پرش به ارجاعات به تعریف یک متد را ارائه می‌دهند، پشتیبانی می‌شود. محیط‌های توسعه می‌توانند این امکانات ناوبری را فراهم کنند زیرا آن‌ها یک مدل به‌روز از فایل‌های منبع را به‌صورت درخت نحو انتزاعی نگهداری می‌کنند.

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

سومین مورد، برای درک استفاده از زبان‌ها باید قادر باشیم عملیات ویرایش صحیح را از عملیات نادرست در محیط توسعه خود تمایز دهیم. محیط‌های توسعه سنتی مدت‌هاست که راهنمایی‌هایی در حین نوشتن برنامه ارائه داده‌اند. کامپایلر تدریجی به محیط اجازه می‌دهد تا پیشنهادات دقیقی به توسعه‌دهنده بدهد مانند اینکه چگونه یک عبارت را تکمیل کند. انواع دیگر راهنمایی‌های مداخله‌گر نیز وجود دارد مانند ویرایشگرهای مبتنی بر نحو که تنها ورودی‌هایی که با گرامر سازگار هستند را می‌توان وارد کرد. ویرایشگرهای متنی عمومی که می‌توانند با گرامر یک زبان پارامتریک شوند، مدت‌هاست که وجود دارند.

ویرایشگرهای موجود هنگام ارائه راهنمایی، روابط سازگاری بین‌زبان‌ها را در نظر نمی‌گیرند. در مثال قبلی، یک ویرایشگر ایده‌آل باید برای مثال قادر باشد سرویس createSurvey را به‌عنوان یک مقدار معتبر هنگام ویرایش ویژگی target در تعریف فرم پیشنهاد کند. محیطی که می‌تواند درباره مصنوعات از زبان‌های مختلف استدلال کند، همچنین قادر خواهد بود به توسعه‌دهنده کمک کند تا وضعیت‌های برنامه‌ای را شناسایی کند که در آن تطابق محلی وجود دارد اما تطابق جهانی نه. چنین وضعیتی زمانی ایجاد می‌شود که یک مدل به‌خوبی شکل‌گرفته است و بنابراین محلی سازگار است، اما در عین حال یک قید بین‌زبان را نقض می‌کند. راهنمایی یا کمک هوشمندانه به‌صورت پیشنهادهایی درباره نحوه تکمیل مدل برای محیط‌های با زبان‌های متعدد و محدودیت‌های پیچیده انطباق مفید خواهد بود. عملیات ویرایشی که توسط ابزارها پیشنهاد می‌شود، می‌تواند فرآیند یادگیری نحوه استفاده از زبان‌ها را برای توسعه‌دهنده آسان‌تر کند.