با آمدن Asp.Net Web API کار ساختن Web APIها برای برنامه نویسها به خصوص دسته ای که با ساخت API و
وب سرویس آشنا نبودند خیلی سادهتر شد . اگر با Asp.Net MVC آشنا باشید
خیلی سریع میتوانید اولین Web Service خودتان را بسازید .
در صفحه مربوط به Asp.Net Web API آمده است که این فریمورک بستر مناسبی برای ساخت و توسعه برنامه های RESTful است . اما تنها ساختن کنترلر و اکشن و برگشت دادن دادهها به سمت کلاینت ، به خودی خود برنامه شما رو تبدیل به یک RESTful API نمیکند .
مثل تمام مفاهیم و ابزارها ، طراحی و ساختن RESTful API هم دارای اصول و Best Practice هایی است که رعایت آنها به خصوص در این زمینه از اهمیت زیادی برخوردار است . همانطور که از تعریف API برمی آید شما در حال طراحی رابطی هستید تا به توسعه دهندگان دیگر امکان دهید از دادهها و یا خدمات شما در برنامهها و سرویس هایشان استفاده کنند . مانند APIهای توئیتر و نقشه گوگل که برنامههای زیادی بر مبنای آنها ساخته شده اند . در واقع توسعه دهندگان مشتریان API شما هستند .
بهره وری توسعه دهنده مهمترین اصل
اینطور میتوان نتیجه گرفت که اولین و
مهمترین اصل در طراحی API باید رضایت و موفقیت توسعه دهنده در درک و
یادگیری سریع API شما ،نه تنها با کمترین زحمت بلکه همراه با حس نشاط ، باشد. ( تجربه کاربری در اینجا هم میتواند صدق کند ). سعی کنید در زمان
انتخاب از بین روشهای طراحی موجود ، از دیدگاه توسعه دهنده به مسئله نگاه کنید .
خود را به جای او قرار دهید و تصور کنید که میخواهید با استفاده از API
موجود یک رابط کاربری طراحی کنید یا یک اپلیکشن برای موبایل بنویسید و اصل را این
نکته قرار دهید که بهره وری برنامه نویس را حداکثر کنید. ممکن است گاهی بین طرحی که بر اساس این اصل برای API خود در نظر داریم و یکی از اصول یا استانداردها تعارض بوجود بیاید . در این موارد بعد از اینکه مطمئن شدیم این اختلاف ناشی از طراحی و درک اشتباه خودمان نیست (که اکثرا هست ) ارجحیت را باید به طراحی بدهیم .
تهیه مستندات API
اگر برای پروژه وب سایتتان هیچ نوشته ای یا توضیحی ندارید ، جالب نیست اما خودتان ساختار برنامه خود را میشناسید و کار را پیش میبرید. اما توسعه دهنده ای که از API شما میخواهد استفاده کند و به احتمال زیاد شما را نمیشناسد ، عضو تیم شما هم نیست ، هیچ ایده ای درباره ساختار آن ، روش نامگذاری توابع و منابع، ساختار Urlها ، چگونگی و گامهای پروسه درخواست تا دریافت پاسخ ندارد ،و به مستندات شما وابسته است و تمام اینها باید در مستندات شما باشد. بیشتر توسعه دهندهها قبل از تست کردن API شما سری به مستندات میزنند ، دنبال نمونه کد آموزشی میگردند و در اینترنت درباره آن جستجو میکنند . ازینرو مستندات ( کارامد ) یک ضرورت است :
1- در مستندات باید هم درباره کلیت و هم در مورد تک تک توابع ( پارامترهای معتبر ، ساختار پاسخها و ... ) توضیحات وجود داشته باشد.
2- باید شامل مثالهایی از سیکل کامل درخواستها / پاسخها باشند .
3- تغییرات اعمال شده نسبت به نسخههای قبلی باید در مستندات بیان شوند .
4- (در وب ) یافتن و جستجو کردن در مستنداتی که به صورت فایل Pdf هستند یا برای دسترسی نیاز به Login داشته باشند سخت و آزاردهنده هستند.
5- کسی را داشته باشید تا با و بدون مستندات با API شما کار کند و از این روش برای تکمیل و اصلاح مستندات استفاده کنید.
رعایت نسخه بندی و حفظ نسخههای قبلی به صورت فعال برای مدت معین
یک API تقریبا هیچوقت کاملا پایدار نمیشود و اعمال تغییرات برای بهبود آن اجتناب ناپذیر هستند . مسئله مهم این است که چطور این تغییرات مدیریت شوند . مستند کردن تغییرات ، اعلام به موقع آنها و دادن یک بازه زمانی کافی برای ارتقا یافتن برنامه هایی که از نسخههای قدیمیتر استفاده میکنند نکات مهمی هستند . همیشه در کنار نسخه بروز و اصلی یک یا دو نسخه ( بسته به API و کلاینتهای آن ) قدیمیتر را برای زمان مشخصی در حالت سرویس دهی داشته باشید .
داشتن یک روش مناسب برای اعلام تغییرات و ارائه مستندات و البته دریافت بازخورد از استفاده کنندگان
تعامل با کاربران برنامه باید از کانالهای مختلف وجود داشته باشد .از وبلاگ ، Mailing List ، Google Groups و دیگر ابزارهایی که در اینترنت وجود دارند برای انتشار مستندات ، اعلام بروزرسانیها ، قرار دادن مقالات و نمونه کدهای آموزشی ، پرسش و پاسخ با کاربران استفاده کنید .
مدیریت خطاها به شکل صحیح که به توسعه دهنده در آزمودن برنامه اش کمک کند.
از منظر برنامه نویسی که از API شما استفاده میکند هرآنچه در آنسوی API اتفاق میافتد یک جعبه سیاه است . به همین جهت خطاهای API شما ابزار کلیدی برای او هستند که خطایابی و اصلاح برنامه در حال توسعه اش را ممکن میکنند . علاوه بر این ، زمانی که برنامه نوشته شده با API شما مورد استفاده کاربر نهایی قرار گرفت ، خطاهای به دقت طراحی شده API شما کمک بزرگی برای توسعه دهنده در عیب یابی هستند .
1- از Status Code های HTTP استفاده کنید و سعی کنید تا حد ممکن آنها را نزدیک به مفهوم استانداردشان بکار ببرید .
2- خطا و علت آن را به زبان روشن توضیح دهید و در توضیح خساست به خرج ندهید .
3- در صورت امکان لینکی به یک صفحه وب که حاوی توضیحات بیشتری است را در خطا بگنجانید .
رعایت ثبات و یکدستی در تمام بخشهای طراحی که توانایی پیش بینی توسعه دهنده را در استفاده از API افزایش میدهد .
داشتن مستندات لازم است اما این بدین معنی نیست که خود API نباید خوانا و قابل پیش بینی باشد . از هر روش و تکنیکی که استفاده میکنید آن را در تمام پروژه حفظ کنید . نامگذاری توابع/منابع ، ساختار پاسخها ، Urlها ، نقش و عملیاتی که HTTP methodها در API شما انجام میدهند باید ثبات داشته باشند . از این طریق توسعه دهنده لازم نیست برای هر بخشی از API شما به سراغ فایلها راهنما برود . و به سرعت کار خود را به پیش میبرد .
انعطاف پذیر بودن API
API توسط کلاینتهای مختلفی و برای افراد مختلفی مورد استفاده قرار میگیرد که لزوما همهی آنها ساختار یکسانی ندارند و API شما باید تا جای ممکن بتواند همه آنها را پوشش دهد . محدود بودن فرمت پاسخ ، ثابت بودن فیلدهای ارسالی به کلاینت ، ندادن امکان صفحه بندی ، مرتب سازی و جستجو در دادهها به کلاینت ، داشتن تنها یک نوع احراز هویت ، وابسته بودن به کوکی و ... از مشخصات یک API منجمد و انعطاف ناپذیر هستند .
اینها اصولی کلی بودند که بسیاری از آنها مختص طراحی API نیستند و در تمام حوزهها قابل استفاده بوده ، جز الزامات هستند . در قسمتهای بعدی نکات اختصاصیتری را بررسی خواهیم کرد .
بازی جدید توسعه برای محصول جدید
SQL Antipattern #1
بخش اول : Jaywalking
در این بخش در حال توسعه ویژگی نرم افزاری هستیم که در آن هرکاربر به عنوان یک کاربر اصلی برای یک محصول تخصیص داده میشود. در طراحی اصلی ما فقط اجازه میدهیم یک کاربر متعلق به هر محصول باشد، اما امکان چنین تقاضایی وجود دارد که چند کاربر نیز به یک محصول اختصاص داده شوند.
در این صورت، اگر پایگاه داده را به نحوی تغییر دهیم که شناسهی حساب کاربران را در لیستی که با کاما از یکدیگر جدا شدهاند ذخیره نماییم، خیلی سادهتر به نظر میرسد نسبت به اینکه بصورت جداگانه آنها را ثبت نماییم.
برنامه نویسان معمولا برای جلوگیری از ایجاد جدول واسطی [1] که رابطههای چند به چند زیادی دارد از یک لیست که با کاما دادههایش از هم جدا شدهاند، استفاده میکنند. بدین جهت اسم این بخش jaywalking ,antipatten میباشد، زیرا jaywalking نیز عملیاتی است که از تقاطع جلوگیری میکند.
1.1 هدف: ذخیره کردن چندین صفت
طراحی کردن جدولی که ستون آن فقط یک مقدار دارد، بسیار ساده و آسان میباشد. شما میتوانید نوع دادهایی که متعلق به ستون میباشد را انتخاب نمایید. مثلا از نوع (int,date…)
چگونه میتوانیم مجموعهایی از مقادیری که به یکدیگر مرتبط هستند را در یک ستون ذخیره نماییم ؟
در مثال ردیابی خطای پایگاه داده، ما یک محصول را به یک کاربر، با استفاده از ستونی که نوع آن integer است، مرتبط مینماییم. هر کاربر ممکن است محصولاتی داشته باشد و هر محصول به یک contact اشاره کند. بنابراین یک ارتباط چند به یک بین محصولات و کاربر برقرار است. برعکس این موضوع نیز صادق است؛ یعنی امکان دارد هر محصول متعلق به چندین کاربر باشد و یک ارتباط یک به چند ایجاد شود. در زیر جدول محصولات را به صورت عادی آورده شده است:
CREATE TABLE Products ( product_id SERIAL PRIMARY KEY, product_name VARCHAR(1000), account_id BIGINT UNSIGNED, -- . . . FOREIGN KEY (account_id) REFERENCES Accounts(account_id) ); INSERT INTO Products (product_id, product_name, account_id) VALUES (DEFAULT, 'Visual TurboBuilder' , 12);
CREATE TABLE Products ( product_id SERIAL PRIMARY KEY, product_name VARCHAR(1000), account_id VARCHAR(100), -- comma-separated list -- . . . ); INSERT INTO Products (product_id, product_name, account_id) VALUES (DEFAULT, 'Visual TurboBuilder' , '12,34' );
اکنون مشکلات کارایی و جامعیت دادهها را در این راه حل پیشنهادی بررسی مینماییم .
بدست آوردن محصولاتی برای یک کاربر خاص
بدلیل اینکه تمامی شناسهی کاربران که بصورت کلید خارجی جدول Products میباشند به صورت رشته در یک فیلد ذخیره شدهاند و حالت ایندکس بودن آنها از دست رفته است، بدست آوردن محصولاتی برای یک کاربر خاص سخت میباشد. به عنوان مثال بدست آوردن محصولاتی که کاربری با شناسهی 12 خریداری نموده بهصورت زیر میباشد:
SELECT * FROM Products WHERE account_id REGEXP '[[:<:]]12[[:>:]]' ;
SELECT * FROM Products AS p JOIN Accounts AS a ON p.account_id REGEXP '[[:<:]]' || a.account_id || '[[:>:]]' WHERE p.product_id = 123;
SELECT product_id, LENGTH(account_id) - LENGTH(REPLACE(account_id, ',' , '' )) + 1 AS contacts_per_product FROM Products;
UPDATE Products SET account_id = account_id || ',' || 56 WHERE product_id = 123;
<?php $stmt = $pdo->query( "SELECT account_id FROM Products WHERE product_id = 123"); $row = $stmt->fetch(); $contact_list = $row['account_id' ]; // change list in PHP code $value_to_remove = "34"; $contact_list = split(",", $contact_list); $key_to_remove = array_search($value_to_remove, $contact_list); unset($contact_list[$key_to_remove]); $contact_list = join(",", $contact_list); $stmt = $pdo->prepare( "UPDATE Products SET account_id = ? WHERE product_id = 123"); $stmt->execute(array($contact_list));
INSERT INTO Products (product_id, product_name, account_id) VALUES (DEFAULT, 'Visual TurboBuilder' , '12,34,banana' );
محدودیت طول لیست
UPDATE Products SET account_id = '10,14,18,22,26,30,34,38,42,46' WHERE product_id = 123;
UPDATE Products SET account_id = '101418,222630,343842,467790' WHERE product_id = 123;
CREATE TABLE Contacts ( product_id BIGINT UNSIGNED NOT NULL, account_id BIGINT UNSIGNED NOT NULL, PRIMARY KEY (product_id, account_id), FOREIGN KEY (product_id) REFERENCES Products(product_id), FOREIGN KEY (account_id) REFERENCES Accounts(account_id) );
جدول
Contacts یک جدول رابطه ایی بین جداول Products,Accounts
بدست آوردن محصولات برای کاربران و موارد مربوط به آن
ما براحتی میتوانیم تمامی محصولاتی که مختص به یک کاربر هستند را بدست آوریم. در این شیوه خاصیت ایندکس بودن شناسهی کاربران حفظ میشود به همین دلیل queryهای آن برای خواندن و بهینه کردن راحتتر میباشند. در این روش به کاراکتری برای جدا کردن ورودیها از یکدیگر نیاز نداریم چون هر کدام از آنها در یک سطر جداگانه ثبت میشوند. برای ویرایش کردن کاربرانی که یک محصول را خریداری نموده اند، کافیست یک سطر از جدول واسط را اضافه یا حذف نماییم. درنمونه کد زیر، ابتدا در جدول Contacts کاربری با شناسهی 34 که محصولی با شناسهی 456 را خریداری کرده، درج شده است و در خط بعد عملیات حذف با شرط آنکه شناسهی کاربر و محصول به ترتیب 34،456 باشد روی جدول Contacts اعمال شده است.
INSERT INTO Contacts (product_id, account_id) VALUES (456, 34); DELETE FROM Contacts WHERE product_id = 456 AND account_id = 34;
ایجاد توابع تجمیعی
به عنوان نمونه در مثال زیر براحتی ما میتوانیم تعداد محصولات در هر حساب کاربری را بدست آوریم:
SELECT account_id, COUNT(*) AS products_per_account FROM Contacts GROUP BY account_id;
اعتبارسنجی شناسه محصولات
از آنجاییکه مقادیری که در جدول قرار دارند کلید خارجی میباشند میتوان صحت اعتبار آنها را بررسی نمود. بعنوان مثال Contacts.account_id به Account.account_id اشاره میکند. در ضمن برای هر فیلد نوع آن را میتوان مشخص کرد تا فقط همان نوع داده را بپذیرد.
محدودیت طول لیست
نسبت به روش قبلی تقریبا در این حالت محدودیتی برای تعداد کاراکترهای ورودی نداریم.
مزیتهای دیگر استفاده از جدول واسط
کارایی روش دوم بهتر از حالت قبلی میباشد چون ایندکس بودن شناسهها حفظ شده است. همچنین براحتی میتوانیم فیلدی را به این جدول اضافه نماییم مثلا (time, date… )
آیا AngularJS تبدیل به استانداردی برای توسعه SPA شدهاست؟
Mono 3.0 منتشر شد
همچنین نسخه دانلودی از اینجا هم قابل دریافت است/خواهد بود: (^)
ضمن اینکه اگر کامنتهای سایت فوق را بررسی کنید، عنوان شده به زودی سایت اصلی را هم به روز خواهند کرد.
21 روش برای فراری دادن برنامه نویسهای خود
4 سطح آزادی برای توسعه دهندگان
(در مورد نوشتن ویرایش محصول هم حق با شماست،متاسفانه بیشتر خریداران به طراحی جلد و جدید بودن کتاب توجه میکنند تا محتوای آن!کتابهای بسیاری هستند که باید گفت افتضا ترجمه شدند ولی فروش بدی نداشتند!)