تفاوت پارادایم‌های برنامه‌نویسی شیءگرا، تابع‌گرا و رویه‌ای (قسمت اول: رویه‌ای)

تفاوت پارادایم های برنامه نویسی شیءگرا، تابع‌گرا و رویه ای (قسمت اول)

تفاوت پارادایم های برنامه نویسی شیءگرا، تابع‌گرا و رویه ای (قسمت اول)

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

  • Object Oriented Programming (برنامه نویسی شیء گرا)
  • Functional Programming (برنامه نویسی تابع‌گرا)
  • Object Oriented Programming (برنامه نویسی رویه ای)

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

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

خلاصه ای از هر سه پارادایم در تئوری

اگر شما کدهای خود را به صورت شیء گرا بنویسید یعنی داده های خود و منطق آن ها را بر اساس اشیاء پیاده می کنید، یعنی کلاس هایی داریم که بعدا اشیائی از آن ها ساخته می شوند و دارای خصوصیت (property) و متد (method) هستند. در برنامه نویسی شیء گرا داده های خودمان را درون خصوصیت ها و منطق اجرایی را درون متدها پیاده می کنیم. در این پارادایم، برنامه ی ما به قسمت های منطقی تقسیم می شود و برنامه را مثل یک پدیده ی واقعی در دنیای واقعی می بینیم. یعنی مثلا اگر می خواهیم یک فروشگاه بسازیم، برای خصوصیات به «سبد» و «محصولات» و... فکر می کنیم و برای متدها چیز هایی مثل «صدور فاکتور» و «دریافت پول» و... را مد نظر قرار می دهیم.

اگر کدهایتان را با پارادایم رویه ای بنویسید یعنی برنامه ی شما «رویه» ی خاصی دارد و کدها به صورت توالی خاصی از عملیات های مختلف هستند. در این حالت کدهای شما از بالا به پایین و خط به خط اجرا می شوند. شاید بگویید که در هر پاردایمی که باشیم اجرای کدها از بالا به پایین است. حرفتان درست است اما منظور من این است که برنامه ی ما شبیه به لیستی از کار ها می شود که موتور زبان برنامه نویسی از بالا تا پایین اجرا می کند. یعنی روند اجرای کد قدم به قدم جلو می رود و از اشیاء برای اجرای کدهایتان استفاده نمی کنید (گرچه خود اشیاء می توانند در کدهایتان حضور داشته باشند).

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

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

شروع عملیات کدنویسی

برنامه ی ما یک دموی بسیار ساده است که یک فایل index.html با محتویات زیر را دارد:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Programming Paradigms</title>
    <link rel="stylesheet" href="app.css" />
  </head>
  <body>
    <form id="user-input">
      <div class="form-control">
        <label for="username">Username</label>
        <input type="text" id="username" />
      </div>
      <div class="form-control">
        <label for="password">Password</label>
        <input type="password" id="password" />
      </div>
      <button type="submit">Create User</button>
    </form>
  </body>
</html>

همانطور که می بینید این کد یک فرم بسیار ساده را به ما نشان می دهد که در فایل app.css استایل های زیر را دارد:

html {
  font-family: sans-serif;
}

form {
  margin: 3rem;
  padding: 1rem;
  border: 1px solid #ccc;
}

.form-control {
  margin: 1rem 0;
}

label, input {
  display: block;
}

label {
  font-weight: bold;
  margin-bottom: 0.5rem;
}

input {
  font: inherit;
  padding: 0.15rem 0.2rem;
  border: 1px solid #ccc;
}

input:focus {
  outline: none;
  background: #e0e0e0;
}

button {
  font: inherit;
  cursor: pointer;
  background: #000057;
  color: white;
  border: 1px solid #000057;
  padding: 1rem 2rem;
}

این استایل ها را نوشته ام تا ظاهر برنامه به هم ریخته نباشد. ظاهر برنامه ی ما به شکل زیر است:

ظاهر ساده ی برنامه ی ما
ظاهر ساده ی برنامه ی ما

شما هم دو فایل index.html و app.css را ایجاد کرده و این کدها را درون آن ها قرار دهید تا کار را شروع کنیم. فعلا این برنامه کاری انجام نمی دهد اما ما می خواهیم کدی ساده برایش بنویسیم تا کار خاصی را بر عهده بگیرد. این برنامه را سه بار در پارادایم های شیء گرا، تابع گرا و رویه ای پیاده خواهیم کرد. من با پارادایم رویه ای شروع می کنم چرا که آسان ترین پارادایم بوده و تقریبا تمام برنامه نویسان از این پارادایم شروع به یادگیری زبان برنامه نویسی می کنند.

پیاده سازی پروژه با پارادایم رویه ای

در ابتدا فایلی به نام procedural.js ایجاد کنید و سپس آن را در تگ های script درون index.html قرار دهید:

    <script src="procedural.js" defer></script>

حالا باید برای شروع به کد html نگاهی بیندازیم و کار را به صورت مرحله به مرحله نگاه کنیم (این تعریف برنامه نویسی رویه ای است):

  • ابتدا باید منتظر submit شدن فرم باشیم.
  • باید مقادیر وارد شده توسط کاربر در فیلدهای username و password را دریافت کنیم.
  • باید مقادیر دریافت شده را اعتبار سنجی کنیم تا فیلدها خالی نباشند.
  • اگر فیلدها خالی بودند پیام خطایی نمایش بدهیم.
  • نهایتا اگر داده ها معتبر بود کاری با آن ها انجام دهیم. مثلا یک شیء جدید می سازیم و آن را درون کنسول مرورگر چاپ می کنیم.

حالا بر اساس این لیستی که از مراحل کار داریم، کدهای خود را در فایل procedural.js می نویسیم. اولین کار دریافت فرم است:

const form = document.getElementById('user-input');

سپس یک event-listener برای ثبت فرم در نظر می گیریم تا هنگام ثبت شدن فرم تابع خاصی اجرا شود:

form.addEventListener('submit', signupHandler);

البته که قدم بعدی تعریف این تابع است:

function signupHandler(event) {

}

form.addEventListener('submit', signupHandler);

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

در قدم بعدی باید مقادیر تایپ شده در فیلدهای یوزرنیم و پسورد را دریافت کنیم البته بعد از اینکه فرم را preventDefault کرده باشیم:

function signupHandler(event) {
  event.preventDefault();

}

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

function signupHandler(event) {
  event.preventDefault();

  const userNameInput = document.getElementById('username');
  const enteredUsername = userNameInput.value;

  const passwordInput = document.getElementById('password');
  const enteredPassword = passwordInput.value;

}

من ابتدا خودِ فیلد را در یک متغیر قرار داده و سپس مقدار تایپ شده در آن را در متغیری دیگر قرار داده ام. البته شما می توانید این کار را در یک خط هم انجام دهید و بستگی به خودتان دارد.

حالا برای قدم بعد باید مطمئن شویم مقادیر تایپ شده توسط کاربر خالی نیست.

function signupHandler(event) {
  event.preventDefault();

  const userNameInput = document.getElementById('username');
  const enteredUsername = userNameInput.value;

  const passwordInput = document.getElementById('password');
  const enteredPassword = passwordInput.value;

  if (enteredUsername.trim().length === 0) {
    alert('Invalid input - username must not be empty!');
    return;
  }
  if (enteredPassword.trim().length <= 5) {
    alert('Invalid input - password must be six characters or longer.');
    return;
  }

}

در شرط اول چک می کنیم که یوزرنیم خالی نباشد و در شرط دوم چک می کنیم که پسورد کمتر از 5 رقم نباشد. من ابتدا روی مقادیر از تابع trim استفاده کرده ام چرا که ممکن است کاربر از space استفاده کرده باشید و اسپیس برای جاوا اسکریپت کاراکتر محسوب می شود. بنابراین با اجرای trim تمام فضاهای خالی را حذف می کنیم تا مشخص شود آیا کاربر واقعا چیزی نوشته است یا خیر. در صورتی که داده های کاربر مطابق شروط تعیین شده ی ما نباشد، با یک پنجره ی alert به او اعلام می کنیم که ورودی مشکل دارد.

از اینجای کار به بعد می دانیم که ورودی ما معتبر است بنابراین می توانیم هر کاری که خواستیم با داده ها انجام دهیم. من همانطور که گفتم یک شیء ساده ی جاوا اسکریپت می سازم و آن را درون کنسول مرورگر چاپ می کنم. بنابراین کد تکمیل شده ی ما به شکل زیر است:

const form = document.getElementById('user-input');

function signupHandler(event) {
  event.preventDefault();

  const userNameInput = document.getElementById('username');
  const enteredUsername = userNameInput.value;

  const passwordInput = document.getElementById('password');
  const enteredPassword = passwordInput.value;

  if (enteredUsername.trim().length === 0) {
    alert('Invalid input - username must not be empty!');
    return;
  }
  if (enteredPassword.trim().length <= 5) {
    alert('Invalid input - password must be six characters or longer.');
    return;
  }

  const user = {
    userName: enteredUsername,
    password: enteredPassword
  };

  console.log(user);
  console.log('Hi, I am ' + user.userName);
}

form.addEventListener('submit', signupHandler);

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

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.