استخراج متن از فایلهای PDF توسط iTextSharp
تعریف متدها در برنامه نویسی:
متدها جزء اولین چیزهایی هستند که در هنگام شروع برنامه نویسی در هر یک از زبانهای برنامه نویسی، برنامه نویس با آنها آشنا میشود. بنابراین متدها به عنوان اصلیترین Building Block ها در زبانهای برنامه نویسی دارای اهمیت بسیار زیادی میباشند. متدها اولین جاهایی هستند که ما میتوانیم کار خودمان را از آنها شروع کنیم و به سوی هدف خود حرکت کنیم.
همان طور که میدانید شما در هنگام کد نویسی یکسری عملکردها را با ارسال یکسری پارمترها به متدها و فراخوانی آنها، بر عهدهی یک متد خاص میگذارید. بعد از فراخوانی انتظار دارید که متد، یک نوع دادهی خاص را برگرداند یا اینکه انتظار ندارید هیچ مقداری را برگرداند. همچنین احتمال دارد در هنگام اجرای متدی، یکسری خطاها رخ دهند و برنامه نویس باید سعی کند همهی آنها را به درستی مدیریت کند. اما آیا به نظر شما مواردی که در مورد متدها دارای اهمیت میباشند، فقط اینها هستند؟
بسیاری از برنامه نویسان انتظاری که از متدها دارند فقط در همین حد میباشد و بیشتر از این درگیر هیچ مسئلهی دیگری نمیشوند. اما آیا فقط در نظر گرفتن این مسایل در رسیدن به یک کد خوش ساخت، قابل توسعه و بدون پیچیدگی کافی است؟
متدها علاوه بر ویژگیهای ذکر شدهی در بالا که بیشتر بر ویژگیهای ذاتی و عملکردی آن تمرکز داشت، باید داری یکسری ویژگیهای دیگر نیز باشند، متدها باید Clean ، Testable و Predictable باشند. هر کدام از ویژگیهای مذکور توسط این پارامترها تشریح میشوند.
در ذیل ویژگیهای مذکور در شکل بالا را تشریح خواهیم کرد.
Clear Purpose :
· یک متد یک کار را انجام میدهد و همچنین آن کار را نیز به خوبی انجام میدهد.
· متد به راحتی قابل درک میباشد.
· میزان خطاها را به شدت کاهش میدهد.
· دیباگ کردن را در صورت وجود هر خطایی سادهتر میکند.
· قابلیت توسعه را افزایش میدهد.
· نوشتن تست برای این نوع متدها به دلیل اینکه فقط بر روی یک هدف خاص تمرکز دارند ساده است.
Good Name :
· نام متد عمکرد آن را به روشنی بیان میکند
Focused Code :
· تمام کد نوشته شدهی در متد فقط بر روی یک هدف تمرکز دارند.
· خوانایی کد بالا است و میزان توضیحاتی که برای کد نوشته میشود در کمترین حد ممکن است.
· متد دارای تاثیرات ناخواستهای بر سایر قسمتهای نرم افزار نمیباشد. این مسئله به معنی است که این نوع متدها شامل کدهایی که کارهای ناخواسته ای را انجام میدهند نمیباشد. برای مثال متدی که برای واکشی اطلاعات مشتریان استفاده میشود هیچگونه عملیاتی را که برای ثبت اطلاعات مشتریان انجام میشود، انجام نمیدهد.
Short Length :
· تعداد خطوط کد مربوط به متد کم میباشد. این مسئله خود باعث کاهش باگهای احتمالی در یک متد میشود.
Automated Code Test :
· متد این قابلیت را دارد که توسط زیر ساختهای تست، تست شود که این مسئله خود باعث افزایش کیفیت کد میشود.
Predictable Result :
· متد دارای یک نتیجهی قابل پیش بینی میباشد.
در ادامه سعی میکنیم با ذکر یک مثال، مواردی را که ذکر شد بیشتر توضیح دهیم و دیدگاه کاربردی آن را بررسی کنیم.
مثالی از دنیای واقعی:
مثال زیر فرآیند مربوط به دریافت سفارش از مشتری را به صورت کدی محاورهای نمایش میدهد. در این مثال سعی شده مشکلات و راه حلهای پیشنهادی Defensive Code با تمرکز بر مواردی که در قسمت قبل ذکر شد به صورت کامل تشریح شود. اکثر ما به عنوان برنامه نویس، با مواردی مانند شکل ذیل مواجه شدهایم. در این حالت در هنگام طراحی نرم افزار برنامه نویس مستقیما وارد رویداد مربوط به کلیک دکمهی ثبت اطلاعات سفارش میشود و به صورت کاملا ناباورانه و با پشتکاری مثال زدنی شروع به کد زدن میکند. برنامه نویس تمامی منطق دریافت اطلاعات از کاربر و ثبت مشترک، ایجاد درخواست برای مشترک، مراحل دریافت کالا از انبار، پرداخت، ارسال ایمیل به مشتری و سایر عملیاتهای دیگر را در این متد و پشت سر هم مینویسد:
این روش کد نویسی روشی است که اکثر برنامه نویسان با آن آشنایی دارند. اولین مشکلی که این روش دارد این است که این کد Clean نمیباشد. قابلیت توسعه و نگهداری این کد بسیار پایین میباشد و به اصطلاح یک کد کاملا باگ خیز میباشد. حال نوبت این رسیده که این کد را از نظر پارامترهایی که در بالا ذکر شد بررسی کنیم.
Clear Purpose :
آیا این متد دارای یک هدف مشخص و معین است؟ بیایید بررسی کنیم، ایجاد مشتری، ایجاد سفارش، ارسال درخواست به انبار، انجام عملیات پرداخت و ارسال رسید. همهی این کارها توسط این متد انجام میشود. خودتان در مورد تبعات این روش کد نویسی قضاوت کنید.
Clear Name :
به نظر شما چگونه میتوان یک اسم مناسب برای این متد انتخاب کرد که عملکرد آن را به درستی بیان کند. هر متد به یک نام مناسب نیاز دارد که این مسئله خود قابلیت توسعه و نگهداری کد را افزایش میدهد. این نام میتواند اطلاعات کاملی را در مورد متد ارائه دهد و عملکرد کلی آن را بیان نماید. هدف متد باید از طریق نام متد بیان شود و هنگامیکه شما نتوانید برای متد مد نظر یک نام را انتخاب کنید، بنابراین این متد دارای هدفی مشخص نمیباشد.
Focused Code :
متد باید کاری را انجام دهد که نام آن بیان میکند و تمام کدهای متد باید حتما بر روی آن هدف تمرکز کنند.
Short Length :
متد باید دارای طول کمی باشد. برای مثال طول کد نباید از اندازهی صفحه نمایش بیشتر باشد. به عبارتی دیگر، کد متد نباید اسکرول بخورد. بنابراین باید سعی شود کدهای اضافی از متد حذف شوند تا با این کار پیچیدگی کد هم به کمترین میزان برسد.
Automated Code Test :
آیا این متد به وسیلهی Automated Code Test می تواند تست شود؟ چند نکته در مورد این کد وجود دارد که توانایی Automated Code Test را از این کد میگیرد. اولین مسئله این است که در این مثال منطق یا همان Business برنامه با UI تلفیق شدهاست. برای رفع این مشکل باید منطق برنامه را در یک پروژهی مجزا از نوع Class Library قرار داد. مسئلهی دیگر این است که این متد برای تست شدن بسیار طولانی میباشد و باید به یکسری اجزای کوچکتر و منطقیتر شکسته شود و هر متد باید یک هدف و عملکرد روشن را داشته باشد.
در قسمت بعدی راهکارهایی برای Refactor کردن کد بر اساس اصول ذکر شده ارائه خواهد شد.
Claim Based Identity
Relying Party (RP) = Application
Service Providers (SP) = Application
RP یا SP یک Application میباشد که از Claim استفاده میکند. واژهی Relying Party بدین دلیل انتخاب شده که Application روی یک Issuer به منظور تامین اطلاعات در مورد یک Identity تکیه میکند.
Subject = User
Principal = User
واژهی Subject یا Principal در حقیقت یک User میباشد. این واژه زمانی معنا پیدا میکند که شما به User به عنوان یک Subject برای کنترل دسترسی، شخصی سازی (Personalization) و ... بنگرید. در Net Framework. به جای Subject از Principal استفاده میشود.
Security Token Service (STC) = Issuer
از دید فنی، STC یک رابط درون یک Issuer میباشد که درخواستها (Request) را تأیید و اقدام به ساخت Issues Security Token (توکنهای مسائل امنیتی) مینماید. توکنهای مسائل امنیتی شامل یک سری Claim میباشند.
Identity Provider (IDP) = Issuer
تامین کننده Identity یک Issuer یا Token Issuer میباشد که وظیفهی تعیین اعتبار (Validation) کاربر مانند نام کاربری، رمز عبور و ... را بر عهده دارد.
Active Client = Smart or rich Client
Passive Client = Browser
یک Active Client میتواند از یک کتابخانهی پیچیده مانند WCF به منظور پیاده سازی پروتکلهایی که بتوانند یک Security Token را درخواست و پاس دهند، استفاده نمایند. به منظور پشتیبانی از مرورگرهای مختلف، سناریوهای passive از پروتکلهای سادهتری به منظور درخواست و پاس دادن یک Security Token که بر روی پروتکل Http تکیه دارد استفاده میکند (Http Post - Http Get).
و اما Claim چیست؟
در حقیقت Claim عبارتست از یک بیانیه یا شرح که یک Subject در مورد خودش یا Subject دیگری میسازد. این بیانیه میتواند در مورد یک نام، هویت، کلید، گروه، حق دسترسی و یا یک قابلیت باشد. Claimها بوسیله یک Provider صادر و سپس بسته بندی (Package) شده و بوسیلهی یک Issuer صادر میشوند که این Issuer عموما با نام Security Token Service شناخته میشود.
به منظور آشنایی با این مبحث میتوانید به اینجا و اینجا مراجعه نمایید.
این نوشتار مقدمهای بود بر مباحث ASP.NET Identity. بنده در حال ترجمهی سه فصل آخر کتاب Pro ASP.NET Mvc 5 Platform که اختصاص به مبحث Identity دارد هستم. فصل 13 تقریبا تمام شده و انشالله بزودی آنرا منتشر میکنم.
پیشنیاز: ایجاد یک برنامهی خالی React و ASP.NET Core
یک پوشهی خالی را ایجاد کرده و در آن دستور dotnet new react را صادر کنید، تا قالب خاص پروژههای React یکی سازی شدهی با پروژههای ASP.NET Core، یک پروژهی جدید را ایجاد کند.
همانطور که در تصویر فوق نیز مشاهده میکنید، این پروژه از دو برنامه تشکیل شدهاست:
الف) برنامهی SPA که در پوشهی ClientApp قرار گرفتهاست و شامل کدهای کامل یک برنامهی React است.
ب) برنامهی سمت سرور ASP.NET Core که یک برنامهی متداول وب، به همراه فایل Startup.cs و سایر فایلهای مورد نیاز آن است.
در ادامه نکات ویژهی ساختار این پروژه را بررسی خواهیم کرد.
تجربهی توسعهی برنامهها توسط این قالب ویژه
اکنون اگر این پروژهی وب را برای مثال با فشردن دکمهی F5 و یا اجرای دستور dotnet run، اجرا کنیم، چه اتفاقی رخ میدهد؟
- به صورت خلاصه برنامهی ASP.NET Core شروع به کار کرده و سبب ارائه همزمان برنامهی SPA نیز خواهد شد.
- پورتی که برنامهی وب بر روی آن قرار دارد، با پورتی که برنامهی React بر روی روی آن ارائه میشود، یکی است. یعنی نیازی به تنظیمات CORS را ندارد.
- در این حالت اگر در برنامهی React تغییری را ایجاد کنیم (در هر قسمتی از آن)، hot reloading آن هنوز هم برقرار است و سبب بارگذاری مجدد برنامهی SPA در مرورگر خواهد شد و برای اینکار نیازی به توقف و راه اندازی مجدد برنامهی ASP.NET Core نیست.
اما این تجربهی روان کاربری و توسعه، چگونه حاصل شدهاست؟
بررسی ساختار فایل Startup.cs یک پروژهی مبتنی بر dotnet new react
برای درک نحوهی عملکرد این قالب ویژه، نیاز است از فایل Startup.cs آن شروع کرد.
// ... using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; namespace dotnet_template_sample { public class Startup { // ... public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); // In production, the React files will be served from this directory services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/build"; }); }
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.2" /> </ItemGroup>
در متد ConfigureServices، ثبت سرویسهای مرتبط با فایلهای استاتیک پروژهی SPA، توسط متد AddSpaStaticFiles صورت گرفتهاست. در اینجا RootPath آن، به پوشهی ClientApp/build اشاره میکند. البته این پوشه هنوز در این ساختار، قابل مشاهده نیست؛ اما زمانیکه پروژهی ASP.NET Core را برای ارائهی نهایی، publish کردیم، به صورت خودکار ایجاد شده و حاوی فایلهای قابل ارائهی برنامهی React نیز خواهد بود.
قسمت مهم دیگر کلاس آغازین برنامه، متد Configure آن است:
// ... using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; namespace dotnet_template_sample { public class Startup { // ... public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ... app.UseStaticFiles(); app.UseSpaStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); }); app.UseSpa(spa => { spa.Options.SourcePath = "ClientApp"; if (env.IsDevelopment()) { spa.UseReactDevelopmentServer(npmScript: "start"); } }); } } }
- متد UseSpaStaticFiles، سبب ثبت میانافزاری میشود که امکان دسترسی به فایلهای استاتیک پوشهی ClientApp حاوی برنامهی React را میسر میکند؛ مسیر این پوشه را در متد ConfigureServices تنظیم کردیم.
- متد UseSpa، سبب ثبت میانافزاری میشود که دو کار مهم را انجام میدهد:
1- کار اصلی آن، ثبت مسیریابی معروف catch all است تا مسیریابیهایی را که توسط کنترلرهای برنامهی ASP.NET Core مدیریت نمیشوند، به سمت برنامهی React هدایت کند. برای مثال مسیر https://localhost:5001/api/users به یک کنترلر API برنامهی سمت سرور ختم میشود، اما سایر مسیرها مانند https://localhost:5001/login قرار است صفحهی login برنامهی سمت کلاینت SPA را نمایش دهند و متناظر با اکشن متد خاصی در کنترلرهای برنامهی وب ما نیستند. در این حالت، کار این مسیریابی catch all، نمایش صفحهی پیشفرض برنامهی SPA است.
2- بررسی میکند که آیا شرایط IsDevelopment برقرار است؟ آیا در حال توسعهی برنامه هستیم؟ اگر بله، میانافزار دیگری را به نام UseReactDevelopmentServer، اجرا و ثبت میکند.
برای درک عملکرد میانافزار ReactDevelopmentServer نیاز است به سورس آن مراجعه کرد. این میانافزار بر اساس پارامتر start ای که دریافت میکند، سبب اجرای npm run start خواهد شد. به این ترتیب دیگر نیازی به اجرای جداگانهی این دستور نخواهد بود و همچنین این اجرا، به همراه تنظیمات proxy مخصوصی نیز هست تا پورت اجرایی برنامهی React و برنامهی ASP.NET Core یکی شده و دیگر نیازی به تنظیمات CORS مخصوص برنامههای React نباشد. بنابراین hot reloading ای که از آن صحبت شد، توسط ASP.NET Core مدیریت نمیشود. در پشت صحنه همان npm run start اصلی برنامههای React، در حال اجرای وب سرور آزمایشی React است که از hot reloading پشتیبانی میکند.
یک مشکل: با این تنظیم، هربار که برنامهی ASP.NET Core اجرا میشود (به علت تغییرات در کدها و فایلهای پروژه)، سبب اجرای مجدد و پشت صحنهی react development server نیز خواهد شد که ... آغاز برنامه را در حالت توسعه، کند میکند. برای رفع این مشکل میتوان این وب سرور توسعهی برنامههای React را به صورت جداگانهای اجرا کرد و فقط تنظیمات پروکسی آنرا در اینجا ذکر نمود:
// replace spa.UseReactDevelopmentServer(npmScript: "start"); // with spa.UseProxyToSpaDevelopmentServer("http://localhost:3000");
تغییرات ویژهی فایل csproj برنامه
اگر به فایل csproj برنامه دقت کنیم، دو تغییر جدید نیز در آن قابل مشاهده هستند:
الف) نصب خودکار وابستگیهای برنامهی client
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') "> <!-- Ensure Node.js is installed --> <Exec Command="node --version" ContinueOnError="true"> <Output TaskParameter="ExitCode" PropertyName="ErrorCode" /> </Exec> <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." /> <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." /> <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" /> </Target>
ب) یکی کردن تجربهی publish برنامهی ASP.NET Core با publish پروژههای React
<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish"> <!-- As part of publishing, ensure the JS resources are freshly built in production mode --> <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" /> <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" /> <!-- Include the newly-built files in the publish output --> <ItemGroup> <DistFiles Include="$(SpaRoot)build\**" /> <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)"> <RelativePath>%(DistFiles.Identity)</RelativePath> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <ExcludeFromSingleFile>true</ExcludeFromSingleFile> </ResolvedFileToPublish> </ItemGroup> </Target>
- ابتدا npm install را جهت اطمینان از به روز بودن وابستگیهای برنامه مجددا اجرا میکند.
- سپس npm run build را برای تولید فایلهای قابل ارائهی برنامهی React اجرا میکند.
- در آخر تمام فایلهای پوشهی ClientApp/build تولیدی را به بستهی نهایی توزیعی برنامهی ASP.NET Core، اضافه میکند.
فرض کنید میخواهید یک فایل ویدیویی با قالب m4v را بر روی تلویزیون خود نمایش دهید؛ اما تلویزیون شما تنها از فایلهای mp4، پشتیبانی میکند. برای رفع این مشکل نیاز به یک نرم افزار تبدیل کنندهی فرمتهای ویدیویی را داریم و یکی از قویترینهای آنها، FFmpeg است. اگر به سایت آن مراجعه کنید، لینک دانلود آن به یک فایل tar.bz2 ختم میشود که حاوی سورس آن است! هرچند در قسمتی از آن، فایلهای نهایی کامپایل شدهی مخصوص سیستم عاملهای مختلف را نیز میتوانید پیدا کنید، اما باز هم با انبوهی از لینکها مواجه خواهید شد که دقیقا مشخص نیست کدام را باید دریافت کرد و آیا نگارش دریافت شده، با سیستم عامل فعلی سازگار است یا خیر.
همانطور که مشاهده میکنید، هنوز هم شروع به کار با نرم افزارهای مختلف برای بسیاری از کاربران، کاری مشکل و طاقتفرسا است. در اینجا شاید این سؤال مطرح شود که این موضوع چه ربطی به Docker (Docker) و کانتینرها (Containers) دارد؟ تمام هیاهویی که پیرامون Docker ایجاد شدهاست، در اصل جهت ساده سازی نصب، راه اندازی و تعامل با نرم افزارهای مختلف است.
چالشهای پیش روی یافتن نرم افزارهای مناسب
این روزها بیشتر نرم افزارهای مورد نیاز خود را از اینترنت تهیه میکنیم. اولین مرحلهی آن و اولین چالشی که در اینجا وجود دارد، یافتن نرم افزاری با مشخصات مدنظر است. برای نمونه حتی اگر با FFmpeg آشنا نیز باشید، به سادگی مشخص نیست که برای سیستم عامل و معماری خاص پردازندهی آن، دقیقا کدام نگارش آنرا از چه آدرسی میتوان دریافت کرد. پس از یافتن نرم افزار و نگارش مدنظر، مرحلهی بعد، استخراج محتویات آن از یک فایل zip و یا اجرای برنامهی نصاب آن است و مرحلهی آخر، اجرای این برنامه میباشد.
بنابراین اولین چالش، یافتن محلی برای دریافت نرم افزار است:
- این روزها برای بعضی از سکوهای کاری، App Storeهایی وجود دارند که میتوان از آنجا شروع کرد؛ اما چنین قابلیتی برای تمام سکوهای کاری پیش بینی نشدهاست.
- در لینوکس قابلیت دیگری به نام Package manager وجود دارد که کار یافتن و نصب نرم افزارها را ساده میکند؛ اما گاهی از اوقات اطلاعات آن، آنچنان به روز نیست. همچنین اگر بستهای برای توزیع خاصی از لینوکس وجود داشته باشد، الزاما به این معنا نیست که این بسته، قابلیت استفادهی در سایر توزیعهای لینوکس را نیز به همراه دارد. در ویندوز نیز وضعیت مشخص است! فاقد یک Package manager توکار و استاندارد است. هرچند یک App Store برای آن از طرف مایکروسافت ارائه شدهاست، اما آنچنان محبوبیتی پیدا نکردهاست.
- و روش متداول دیگری که وجود دارد، مراجعهی مستقیم به سایت اصلی سازندهی نرم افزار است.
- علاوه بر اینها داشتن یک سری متادیتا و آمار نیز در مورد نرم افزارها بسیار مفید هستند تا بتوانند در مورد تصمیم به استفاده، یا عدم استفادهی از نرم افزار، راهنمای کاربران باشند؛ مانند میزان محبوبیت، تعداد بار دریافت، تعداد مشکلاتی که کاربران با آن داشتهاند و آخرین باری که نرم افزار به روز شدهاست. اما با توجه به پراکندگی روشهای دریافت نرم افزار که ذکر شدند، عموما یک چنین آمارهایی را مشاهده نمیکنیم.
- چالش دیگر، مشکل سخت اطمینان کردن به روشهای مختلف توزیع نرم افزارها است. آیا سایتی که این نرم افزار را ارائه میدهد، واقعا مرتبط با نویسندهی اصلی آن است؟ همچنین آیا خود نرم افزار مشکلات امنیتی را به همراه ندارد؟ چه کاری را انجام میدهد؟
- مشکل بعدی، در دسترس بودن سایت توزیع کنندهی نرم افزار است. آیا زمانیکه به برنامهای نیاز داریم، پهنای باند سایت توزیع کنندهی آن تمام نشدهاست و میتوان به آن دسترسی داشت؟
- چالش دیگر، چگونگی پرداخت مبلغی برای دسترسی به نرم افزار است. به نظر تا به اینجا تنها App Storeها موفق شدهاند روشی یک دست را برای خرید برنامهها و همچنین ارائهی مجوزی برای استفادهی از آنها، ارائه دهند.
چالشهای پیش روی نصب نرم افزارها
زمانیکه به مرحلهی نصب نرم افزار میرسیم، هر نرم افزار، روش نصب و تنظیمات آغازین خاص خودش را دارد.
- اولین چالش پس از دریافت نرم افزار، بررسی سازگاری آن با سیستم عامل و پردازندهی فعلی است. شاید این مسایل برای توسعه دهندگان نرم افزارها پیشپا افتاده به نظر برسند، اما برای عموم کاربران، چالشی جدی به شما میروند.
- پس از مشخص شدن سازگاری یک نرم افزار با سیستم فعلی، قالب ارائهی آن نرم افزار نیز میتوان مشکلزا باشد. بعضی از برنامهها صرفا از طریق سورس کد منتشر میشوند. بعضی از آنها توسط یک فایل exe متکی به خود ارائه میشوند و بعضی دیگر به همراه یک فایل exe و تعدادی dll به همراه آنها. گاهی از اوقات این برنامهها نیاز به نصب جداگانهی NET Runtime. و یا Java Runtime را برای اجرا دارند و یا وابستگی آنها صرفا به نگارش خاصی از این کتابخانهها و فریم ورکهای ثالث است. هرچند اگر برنامهای به همراه بستهی نصاب آن باشد، به احتمال زیاد این وابستگیها را نیز نصب میکند؛ اما تمام برنامهها اینگونه ارائه نمیشوند. به علاوه خیلیها علاقهای به کار با برنامههای نصاب ندارند و از ایجاد تغییرات بسیاری که آنها در سیستم ایجاد میکنند، خشنود نیستند.
- پس از نصب نرم افزار، مشکل بعدی، نحوهی به روز رسانی آنها است. چگونه باید اینکار انجام شود؟ (تمام مراحل و چالشهایی را که تاکنون بررسی کردیم، یکبار دیگر از ابتدا مرور کنید!)
بنابراین همانطور که مشاهده میکنید، نصب، راه اندازی و به روز رسانی نرم افزارها این روزها بسیار پیچیده شدهاند و بسیاری از کاربران به سادگی از عهدهی آنها بر نمیآیند.
چالشهای پیش روی کار با نرم افزارها
مرحلهی بعد، نیاز به مستندات کافی برای کار با برنامه است. این مستندات را از کجا میتوان تهیه کرد؟ آخرین باری که به روز شده، چه زمانی بودهاست؟ بسیاری از اوقات بین مستندات تهیه شده و آخرین نگارش نرم افزار، ناسازگاری وجود دارد و به سختی قابل استفادهاست. آیا نیاز است برنامه را به PATH اضافه کرد؟ آیا نیاز است به صورت سرویس نصب شود؟ اگر بله، چگونه باید این مراحل را انجام داد؟ مجوز کار کردن با آنها چگونه است؟
مشکل مهم دیگری که حین کار با نرم افزارها، در حالت متداول آنها وجود دارد، دسترسی کامل آنها به تمام اجزای سیستم و شبکه است و درون یک sandbox (قرنطینه) امنیتی اجرا نمیشوند.
مشکل بعدی، به روز رسانی اجزای ثالث سیستم و یا حتی خود سیستم عامل، مانند به روز رسانی OpenSSL نصب شده و پس از آن، از کار افتادن برنامهای خاص است که وابستگی به نگارشی خاص از این کتابخانه را دارد.
کانتینرها در مورد برنامهها هستند و نه مجازی سازی
خوب، تا اینجا دریافتیم که مدیریت توزیع، نصب و استفادهی از برنامهها، کار سادهای نیست. اما اینها چه ارتباطی با Docker دارند؟ در بسیاری از اوقات، زمانیکه صحبت از Docker میشود، تصور بسیاری از آن، ارائهی جایگزینی برای ماشینهای مجازی است. اما ... اینگونه نیست. کانتینرها در مورد نرم افزارها هستند. برای مثال در آینده در مورد ایمیجهای (Images) کانتینرها بیشتر بحث خواهیم کرد. این ایمیجها در اصل یک بستهی حاوی برنامهها هستند. بنابراین بیشتر شبیه به فایل zip ای است که از یک وب سایت دریافت میکنیم (در قسمت یافتن نرم افزار).
یک کانتینر (Container) چیست؟
برای درک بهتر مواردی که تاکنون بحث شدند و همچنین بررسی مفهوم Containers، ابتدا MonogoDB را به صورت معمول نصب میکنیم. سپس نحوهی نصب آنرا درون یک Container بررسی خواهیم کرد. البته هدف اصلی در اینجا، بررسی مفهومی این مراحل و مقایسهی آنها با هم هستند و در قسمتهای بعدی کار نصب و استفادهی از Docker را قدم به قدم بررسی خواهیم کرد.
مراحل نصب محلی MongoDB به صورت متداول:
- ابتدا برای مثال به سایت گوگل مراجعه کرده و mongodb را جستجو میکنیم تا بتوانیم به سایت اصلی و محل دریافت بستهی آن، هدایت شویم.
- پس از ورود به سایت mongodb، در بالای صفحه اصلی آن، لینک به صفحهی دریافت بستهی mongodb را میتوان مشاهده کرد.
- با انتخاب آن، به صفحهی دریافت بستهی mongodb بر اساس سیستم عاملهای مختلفی هدایت میشویم. برای مثال در ویندوز، بستهی msi آنرا دریافت میکنیم.
- به نظر میرسد که بستهی نصاب msi آن تمام کارهای لازم برای راه اندازی اولیهی mongodb را انجام میدهد. به همین جهت آنرا اجرا کرده و پس از چندبار انتخاب گزینهی next، نصب آن به پایان میرسد.
- پس از پایان نصب، ابتدا به کنسول service.msc ویندوز مراجعه میکنیم تا مطمئن شویم که سرویس آن، توسط نصاب msi نصب شدهاست یا خیر؟ و ... خیر! این نصاب، سرویس آنرا نصب نکردهاست.
- به همین جهت به مستندات نصب آن در سایت mongodb مراجعه میکنیم (لینک Installation instructions در همان صفحهی دریافت بستهی msi وجود دارد). پس از پایان مراحل نصب، عنوان کردهاست که باید دستور md \data\db را اجرا کنید تا مسیر پیش فرض اطلاعات آن به صورت دستی ایجاد شود. اما ... این مسیر دقیقا به کجا اشاره میکند؟ چون شبیه به مسیرهای ویندوزی نیست.
- در ادامه برای آزمایش، به پوشهی program files ویندوز رفته، monogodb نصب شده را یافته و سپس فایل mongod.exe را از طریق خط فرمان اجرا میکنیم (برنامهی سرور). اگر این کار را انجام دهیم، این پروسه با نمایش خطای یافت نشدن مسیر c:\data\db، بلافاصله خاتمه پیدا میکند. به همین جهت در همین مسیری که در خط فرمان قرار داریم (جائیکه فایل mongod.exe قرار دارد)، دستور md \data\db را اجرا میکنیم. اجرای این دستور در این حالت، همان پوشهی c:\data\db را ایجاد میکند. نکتهای که شاید خیلیها با آن آشنایی نداشته باشند.
- اکنون اگر مجددا فایل mongod.exe را اجرا کنیم، اجرای آن موفقیت آمیز خواهد بود و پیام منتظر دریافت اتصالات بودن از طریق پورت 27017 را نمایش میدهد.
- مرحلهی بعد، اجرای فایل mongo.exe است تا به این دیتابیس سرور در حال اجرا متصل شویم (برنامهی کلاینت). در اینجا برای مثال میتوان دستور show dbs را اجرا کرد تا لیست بانکهای اطلاعاتی آنرا نمایش دهد.
مراحل نصب MongoDB به صورت Container توسط Docker:
- ابتدا برای مثال به سایت گوگل مراجعه کرده و اینبار mongodb docker را جستجو میکنیم تا بتوانیم به محل دریافت image آن هدایت شویم. با ورود به آن، در بالای صفحه عنوان شدهاست که official repository است که سبب اطمینان از بستهی ارائه شدهی توسط آن میشود. بنابراین در اینجا بجای مراجعه به سایت متکی به خود mongodb، به docker hub برای دریافت آن مراجعه کردهایم. در اینجا با جستجوی یک برنامه، متادیتا و اطلاعات آماری بسیاری را نیز میتوان در مورد برنامههای مختلف، مشاهده کرد که در سایت متکی به خود نرم افزارهای مختلف، در دسترس نیستند. همچنین در اینجا اگر بر روی برگهی Tags یک مخزن کلیک کنید، مشاهده میکنید که تمام فایلهای موجود در آن توسط docker hub از لحاظ مشکلات امنیتی پیشتر اسکن شدهاند و گزارش آنها قابل مشاهدهاست. علاوه بر اینها docker hub به همراه یک docker store برای برنامههای غیر رایگان نیز هست و این مورد فرآیند کار با نرم افزارهای تجاری را یک دست میکند.
- مرحلهی بعد، دریافت یک کپی از mongodb از docker hub است. اینبار بجای دریافت مستقیم یک فایل zip یا msi، از دستور docker pull mongo استفاده میشود که یک image را در نهایت دریافت میکند. این image، حاوی برنامهی مدنظر و تمام وابستگیهای آن است.
- پس از دریافت image، مرحلهی بعد، اجرای mongodb به همراه آن است. در حالت متداول، ابتدا نرم افزار داخل فایل zip یا msi استخراج شده و سپس بر روی سیستم اجرا میشوند، اما در اینجا مفهوم معادل نصب نرم افزار دریافت شدهی از بستهی zip همراه آن، یک container است. یک container دقیقا مانند یک نرم افزار از پیش نصب شده، عمل میکند و معادل اجرای فایل exe مانگو دی بی در اینجا، اجرای container آن است. بنابراین docker، از image دریافت شده، یک container را ایجاد میکند که دقیقا معادل یک نرم افزار از پیش نصب شده، رفتار خواهد کرد.
- پس از دریافت image، جهت اجرای آن به عنوان یک container، برای استفاده از نرم افزاری که دریافت کردهایم، تنها یک دستور است که باید با آن آشنا باشیم: docker run mongo. این دستور را در همان صفحهی docker hub مربوطه نیز میتوانید مشاهده کنید. پس از اجرای این دستور، دقیقا همان خروجی و پیام منتظر دریافت اتصالات بودن از طریق پورت 27017 را مشاهده خواهیم کرد. برای اجرای کلاینت آن نیز دستور docker exec -it 27 mongo را میتوان اجرا کرد. docker exec کار اجرای چندبارهی یک نرم افزار نصب شده را انجام میدهد.
این فرآیند در مورد تمام containerها یکی است و به این ترتیب به ازای هر نرم افزار مختلف، شاهد روش نصب متفاوتی نخواهیم بود.
- اجرای دستور docker stop نیز سبب خاتمهی تمام اینها میشود.
در این تصویر مقایسهای را بین مراحل متداول یافتن، دریافت، نصب و اجرای برنامهها را در دو حالت متداول و همچنین استفادهی از docker، مشاهده میکنید.
همچنین نکتهی جالبی که در مورد docker وجود دارد این است که اگر به task manager ویندوز مراجعه کنیم:
تمام پروسههایی که با job id مساوی 172 در اینجا اجرا شدهاند، متعلق به docker بوده و آنها دقیقا مانند یک پروسهی معمولی سیستم عامل جاری، در کنار سایر پروسههای موجود، اجرا میشوند. بنابراین برنامهای که از طریق docker اجرا میشود، هیچ تفاوتی با اجرای متداول آن بر روی سیستم عامل، از طریق روش مراجعهی مستقیم به فایل exe مرتبط و اجرای مستقیم آن ندارد. همانطور که پیشتر نیز عنوان شد، containerها در مورد نرم افزارها هستند و نه مجازی سازی و یک container در حال اجرا، حاوی تعدادی برنامهی در حال اجرای بر روی سیستم عامل جاری، در کنار سایر برنامههای آن میباشد.
البته containers به همراه ایزوله سازیهای بسیاری اجرا میشوند. برای مثال به روز رسانی یک کتابخانهی ثالث بر روی سیستم عامل، سبب از کار افتادن برنامهی اجرای شدهی توسط یک container نمیشود.
در قسمت بعد، نحوهی نصب Docker را بر روی ویندوز، بررسی میکنیم.