# milon.im — full Markdown dump for agentsGenerated for LLM ingestion. Prefer individual `.md` URLs when possible; this file is the offline-friendly concatenation.Source: https://milon.im/ --- # Nuruzzaman Milon > Programmer, author, and speaker. Engineering Tech Lead building production systems that serve millions. ## Recently At Punt I took the backend API suite to 16k concurrent users and cut redemption fraud by 38%. Before that I shipped gift-card systems at Amazon and network inventory for FlixBus across 38 countries. I also wrote [Laravel After Deploy](https://laravel-after-deploy.milon.im/), a production playbook for Laravel at scale. See the [full CV](/cv.md). ## About I grew up in Dhaka, Bangladesh, and now live near Vancouver, British Columbia. Most of my days are spent on systems that have to stay up for millions of people: architecture, performance, and the unglamorous work that happens after deploy. I write and speak about that work — what it actually takes to keep Laravel systems running once they leave a laptop. Outside of work I cook and publish recipes, and I have developed a late interest in cars. I am the parent of a son and two daughters. ## Writing - [Database partitioning](/post/database-partitioning.md): What table partitioning actually does, how Postgres routes a row, and the SQL you need before the table is too big to rewrite. - [Two-phase commit](/post/two-phase-commit.md): What two-phase commit actually does, where it fails in production, and what to reach for instead. - [Adding multiple subdomain with Github Pages](/post/adding-multiple-subdomain-with-github-pages.md): How to add multiple subdomain with Github Pages? - [Build and deploy Jigsaw site with Github Actions](/post/github-action-with-jigsaw.md): How to build and deploy a site built with Jigsaw static generator with Github Actions. - [Added search functionality with fuse.js in Jigsaw powered site](/post/added-search-functionality-with-fusejs-in-jigsaw-powered-site.md): Added fuzzy search with fuse.js in static site generated with Jigsaw. - [All writing](/posts.md) ## Books - [Laravel After Deploy](https://laravel-after-deploy.milon.im/): Production playbook for mid-to-senior engineers (2026, English) - [Laravel PHP Web Framework](/book/laravel.md): Bengali-language introduction to Laravel (2015) ## Talks - [Why you should consider statically generated site for your next website?](/talk/why-you-should-consider-statically-generated-site-for-your-next-website.md): I presented this on an audiance for an online PHP meetup in Berlin. - [Klassroom presents the Techtalk: Scaling API with Laravel](/talk/klassroom-presents-techtalk-scaling-api-with-laravel.md): I was interviewed by Sumon Molla Selim on his web podcast about APIs and how to create them with Laravel. - [Telenor Health - Tonic Application Architecture](/talk/th-tonic-application-architecture.md): I presented this on an internal session to all the team members of Telenor Health including developers, dev ops, QA and all. - [All talks](/talks.md) ## Open source - [milon/barcode](https://github.com/milon/barcode): barcode generation for Laravel and plain PHP (16.1M Packagist downloads) - [All open source](/open-source.md) ## More - [CV](/cv.md) - [Contact](/contact.md) - [Logo](/logo.md) - [Atom feed](/feed.xml) - [Full site for LLMs](/llms-full.txt) --- # Curriculum Vitae > Engineering Tech Lead · Vancouver, British Columbia. HTML: [/cv](/cv). PDF: [/assets/pdf/Nuruzzaman_Milon_cv.pdf](/assets/pdf/Nuruzzaman_Milon_cv.pdf). ## Contact - Email: [contact@milon.im](mailto:contact@milon.im) - Phone: +1 (604) 735-7681 - Site: [milon.im](https://milon.im/) - LinkedIn: [/linkedin](/linkedin) - GitHub: [/github](/github) - X: [/x](/x) ## Summary Software engineer with over a decade of experience across healthcare, travel, ecommerce, and gaming. Leads backend teams shipping production systems that have to stay up — architecture, performance, fraud controls, and post-deploy operations. Strongest in Laravel/PHP, with production experience in Java, TypeScript, React, and AWS. ## Experience ### Punt — Vancouver, BC, Canada **Engineering Tech Lead** — January 2026 – Present - Lead the engineering team for the sweepstakes casino: backend API suite and admin panel. - Spearheaded platform expansion into new markets, including Canada and Europe. - Drive code quality and architectural decisions across the organization. **Senior Software Engineer** — January 2025 – January 2026 - Rewrote the legacy admin panel for chanced.com and punt.com. - Optimized the backend API suite to handle 16k concurrent users. - Migrated the backend API suite to current Laravel and PHP versions. - Built fraud detection for redemptions, cutting fraudulent activity by 38%. - Implemented load-testing infrastructure simulating up to 25k concurrent users. - Technologies: PHP, Laravel, PostgreSQL, Redis, React, Docker, AWS, k6 ### Amazon — Canada **Software Development Engineer II** — December 2023 – December 2024 · Vancouver, BC - Gift Card Fulfillment and Delivery Charter team. - Migrated the Gift Card Organization’s email suite to Amazon’s new templating system. - Technologies: Java, TypeScript, React, AWS **Software Development Engineer II** — February 2023 – November 2023 · Toronto, ON - Amazon Connections, UX Tech team. ### Flix — Berlin, Germany **Senior Software Engineer** — January 2020 – January 2023 - Network inventory, ride generation, and vehicle circulation for FlixBus and FlixTrain across 38 countries on 4 continents. - Proprietary navigation for bus drivers in FlixDriver; lost-and-found reporting that reduced lost-baggage claims by 44%. - Technologies: PHP, Laravel, Symfony, Java, Kotlin, React Native, Kafka, SQS, MySQL, Docker, AWS, Kubernetes, GitLab CI, React, TypeScript ### Urban Sports Club — Berlin, Germany **Senior Software Engineer** — July 2019 – December 2019 - Multi-currency payment system and new payment gateways; financing, payments, and GDPR. - Technologies: PHP, Laravel, Symfony, Phalcon, MySQL, RabbitMQ, Redis, AWS ### Check24 — Münster, NRW, Germany **Senior Software Engineer** — May 2018 – June 2019 - Tires, car parts, and insurance portals for Autoteile, serving over 10 million customers. - Technologies: PHP, Symfony, Laravel, MySQL, Doctrine, React, Elasticsearch ### Telenor Health — Dhaka, Bangladesh **Senior Software Engineer** — May 2016 – April 2018 - Digital healthcare reaching over 5.5 million people; managed 4 developers, 3 interns, 1 QA, 1 DevOps. - SMS gateway at 3k req/s; CMS reaching 10 million people. - Technologies: PHP, Laravel, Lumen, Node.js, Express.js, PostgreSQL, Jenkins, Docker, AWS, Ansible, Angular, XMPP ### WeDevs Ltd. — Dhaka, Bangladesh **Software Engineer** — February 2015 – April 2016 - Rx71 health service; managed 6 developers, 2 SQA, 1 DevOps; interim CTO for 3 months. - Technologies: PHP, Laravel, Lumen, WordPress, MySQL, Angular, IonicJS, socket.io ### Brotecs Technologies Ltd. — Dhaka, Bangladesh **Software Engineer** — September 2013 – January 2015 - Native Android/iOS VoIP apps; Asterisk PABX GUI; airplane entertainment module for SAP-212. - Technologies: PHP, CodeIgniter, Android SDK, Objective-C, Angular, Asterisk ### ITMedicus Bangladesh Ltd. — Dhaka, Bangladesh **Programmer and System Analyst** — February 2011 – August 2013 - Telemedicine software for custom hardware in rural healthcare; owned codebase, database, and client communication. - Technologies: PHP, MySQL, Redis, jQuery, Bootstrap ## Education **Mawlana Bhashani Science and Technology University** — Tangail, Bangladesh B.Sc. Engineering in Information and Communication Technology (ICT) - President, Society of ICT - Chief Organizer, 1st MBSTU ICT Fest - Member, Rotary Club of MBSTU ## Books - [Laravel After Deploy](https://laravel-after-deploy.milon.im/) (August 2026, ISBN 979-8193747345) — production playbook for Laravel at scale. - [Laravel PHP Web Framework](/book/laravel.md) (May 2015, ISBN 978-9843391902) — two bestselling editions in Bangladesh and West Bengal. ## Skills - Languages: PHP, Java, Python, Node - Frameworks: Laravel, Symfony, React, Vue - Data: PostgreSQL, MySQL, Redis, Elasticsearch, MongoDB, DynamoDB, Kafka, RabbitMQ - Cloud / Ops: AWS, Docker, Kubernetes, Jenkins, Ansible, Nginx - Practices: Microservices, REST, GraphQL, TDD, DDD, Agile / Scrum / Kanban ## Certifications - Certified Laravel Developer — 2018 - Certified Scrum Professional — Developer — 2018 - Certified Scrum Professional — ScrumMaster — 2017 - Advanced Certified Scrum Developer — 2017 - Certified Scrum Developer — 2017 - Certified ScrumMaster — 2016 ## More - Languages spoken: English (C1), Bengali (native), German (A2) - [Open-source packages](/open-source.md) with over 15 million downloads - Manages phpXperts and Talk.js in Bangladesh - Conference speaker --- # Contact > The fastest way to reach me is email. I read everything, and I reply to most of it. HTML: [/contact](/contact). ## Direct - **Email:** [contact@milon.im](mailto:contact@milon.im) - **Website:** [milon.im](https://milon.im) - **X:** [@to_milon](/x) — best for a quick response - **LinkedIn:** [in/tomilon](/linkedin) ## Elsewhere - [GitHub](/github) - [Facebook](/facebook) - [SlideShare](/slideshare) - [Speaker Deck](/speakerdeck) - [Instagram](/instagram) - [Stack Overflow](/stackoverflow) ## Newsletter Subscribe from the HTML contact page ([/contact](/contact)) — the form posts to Kit (ConvertKit). --- # Open Source > PHP packages on Packagist, led by a barcode library with 16.1M downloads. HTML: [/open-source](/open-source). ## Featured ### milon/barcode - **Downloads:** 16.1M - **Downloads / month:** 582.8k - **GitHub stars:** 1.5k - **Forks:** 330 - **Stack:** PHP · Laravel - **Packagist:** [https://packagist.org/packages/milon/barcode](https://packagist.org/packages/milon/barcode) - **GitHub:** [https://github.com/milon/barcode](https://github.com/milon/barcode) Barcode generation for Laravel and plain PHP. Wraps the TCPDF barcode engines (1D, QR, Data Matrix, PDF417) behind a small API that returns SVG, HTML, PNG, and JPEG — still maintained across current Laravel releases. ## Projects - [papyrus](https://github.com/milon/papyrus) — PHP CLI for Markdown book projects — PDF, EPUB, HTML, multi-page site, and Amazon KDP exports. - [fuse](https://github.com/milon/fuse) — HTTP-client-agnostic circuit breaker for PHP 8.2+ — optional Laravel and Saloon adapters. - [setu](https://github.com/milon/setu) — Setu (সেতু, bridge) — generate a static URL shortener for GitHub Pages from a JSON map of slugs to URLs. - [prepare-citizenship](https://github.com/milon/prepare-citizenship) — Study for the Canadian citizenship test with chapter lessons, flashcards, and mock exams. - [bohurupee](https://github.com/milon/bohurupee) — Local fake identity provider for OAuth and OpenID Connect — point any client at localhost and sign in as a persona. - [jigsaw-url-shortener](https://github.com/milon/jigsaw-url-shortener) — URL shortener package for Jigsaw-powered static sites. - [macos-unijoy](https://github.com/milon/macos-unijoy) — Unijoy Bengali keyboard layout for macOS. - [dotfiles](https://github.com/milon/dotfiles) — Personal macOS dotfiles and shell setup. - [system-design](https://github.com/milon/system-design) — Notes and preparation for system design interviews. - [one-problem-a-day](https://github.com/milon/one-problem-a-day) — One data-structure or algorithms problem a day. - [recipes](https://github.com/milon/recipes) — Recipe sharing site — also live at recipes.milon.im. - [catppuccin-fresh](https://github.com/milon/catppuccin-fresh) — Catppuccin color schemes for Fresh Editor — Mocha, Macchiato, Frappé, and Latte. - [arrow-zsh-theme](https://github.com/milon/arrow-zsh-theme) — A minimal theme for the zsh shell. - [takakori](https://github.com/milon/takakori) — Self-hosted personal finance app. - [url-shortener](https://github.com/milon/url-shortener) — A simple URL shortener built with Laravel. This is a selection. The full list of repositories and contributions is on [GitHub](/github). ## Elsewhere - [GitHub profile](/github) - [Packagist vendor](https://packagist.org/packages/milon/) - [npm profile](https://www.npmjs.com/~to_milon) Also helps run phpXperts and Talk.js, the largest PHP and JavaScript communities in Bangladesh. --- # Books > Two books on Laravel, written a decade apart, for two very different readers. HTML: [/books](/books). ## Laravel After Deploy - **Subtitle:** Architecture, Performance & Operations at Scale - **Language:** English - **Published:** 2026 · August - **ISBN:** 979-8193747345 - **Site:** [laravel-after-deploy.milon.im](https://laravel-after-deploy.milon.im/) For mid-to-senior Laravel engineers, and for backend engineers who can read PHP and want a production playbook shown in one concrete stack — not a polyglot cookbook. The examples are Laravel; the problems are not. ## Laravel PHP Web Framework - **Title (Bengali):** লারাভেল পিএইচপি ওয়েব ফ্রেমওয়ার্ক - **Publisher:** Dimik Prokashoni · two editions - **Language:** Bengali - **First edition:** 2015 · May - **ISBN:** 978-9843391902 - **Details:** [/book/laravel.md](/book/laravel.md) A Bengali-language introduction to Laravel for PHP developers looking to adopt modern framework practices. --- # Writing > Essays on Laravel, architecture, performance, and building software that has to stay up. 80 posts, newest first. Prefer the Markdown links. HTML: [/posts](/posts). Atom feed: [/feed.xml](/feed.xml). - [Database partitioning](/post/database-partitioning.md) — 2026-08-21 — What table partitioning actually does, how Postgres routes a row, and the SQL you need before the table is too big to rewrite. - [Two-phase commit](/post/two-phase-commit.md) — 2026-08-20 — What two-phase commit actually does, where it fails in production, and what to reach for instead. - [Adding multiple subdomain with Github Pages](/post/adding-multiple-subdomain-with-github-pages.md) — 2023-10-10 — How to add multiple subdomain with Github Pages? - [Build and deploy Jigsaw site with Github Actions](/post/github-action-with-jigsaw.md) — 2020-07-13 — How to build and deploy a site built with Jigsaw static generator with Github Actions. - [Added search functionality with fuse.js in Jigsaw powered site](/post/added-search-functionality-with-fusejs-in-jigsaw-powered-site.md) — 2020-04-21 — Added fuzzy search with fuse.js in static site generated with Jigsaw. - [Why you should know analyzing space-time complexity as a software engineer?](/post/why-you-should-know-analyzing-space-time-complexity-as-a-software-engineer.md) — 2019-03-11 — Importance of space time complexity analysis in software engineering field. - [Naming a variable](/post/naming-a-variable.md) — 2018-02-04 — My two cents on naming a variable while programming. - [Story behind my new blog](/post/story-behind-my-new-blog.md) — 2018-01-23 — The behind story of my statically generated github pages powered blog. - [How to become a Certified Laravel Developer](/post/how-to-become-a-certified-laravel-developer.md) — 2018-01-09 — The steps of becoming a Certified Laravel Developer. - [Machine Learning Introduction – 1: Set up your workstation](/post/machine-learning-introduction-1-set-up-your-workstation.md) — 2017-02-23 — Setting up your workstation for practicing Machine Learning. - [Why you should consider laravel as your go to framework of choice](/post/why-you-should-consider-laravel-as-your-go-to-framework-of-choice.md) — 2017-02-04 — My thoughts on Laravel framework, and it's usability. - [লারাভেল ভ্যালে ইনস্টলেশন](/post/laravel-valet-installation.md) — 2016-05-09 — কিভাবে লারাভেল ভ্যালে ইনস্টল এবং কনফিগার করবেন আপনার ওয়ার্কস্টেশনে। - [Adminer, a great tool for accessing databases](/post/adminer-a-great-tool-for-accessing-databases.md) — 2016-04-19 — My thoughts on single file RDBMS management tool Adminer. - [Never use rm, instead use trash](/post/never-use-rm-instead-use-trash.md) — 2016-03-19 — I thoughts on why everyone should use `trash` command instead of using `rm`. - [Setting Up Atom Editor for Software Development – 04](/post/atom-editor-for-software-development-04.md) — 2016-03-07 — This is the forth part of my setting up development environment in Atom editor by Github. - [Setting Up Atom Editor for Software Development – 03](/post/atom-editor-for-software-development-03.md) — 2016-03-06 — This is the third part of my setting up development environment in Atom editor by Github. - [Setting Up Atom Editor for Software Development – 02](/post/atom-editor-for-software-development-02.md) — 2016-03-03 — This is the second part of my setting up development environment in Atom editor by Github. - [Setting Up Atom Editor for Software Development – 01](/post/atom-editor-for-software-development-01.md) — 2016-03-02 — This is the first part of my setting up development environment in Atom editor by Github. - [লারাভেলে একাধিক রাউটিং ফাইলের ব্যবহার](/post/laravel-multiple-route-files.md) — 2016-02-16 — লারাভেলে একাধিক রাউটিং ফাইল ব্যবহার বিধি। (আপডেট: লারাভেল ৫.৫ এ এই ফিচারটি যুক্ত করা হয়েছে।) - [লারাভেল হোমস্টিড ইনস্টলেশন](/post/laravel-homestead-installation.md) — 2016-02-10 — লারাভেল হোমস্টিডের মাধ্যমে ডেভেলপমেন্ট এনভায়রনমেন্ট তৈরি করা। - [উবুন্টুতে রেডিস ইনস্টল](/post/install-redis-in-ubuntu.md) — 2015-07-06 — উবুন্টু অপারেটিং সিস্টেমে রেডিস ইনস্টলেশন গাইডলাইন। - [লারাভেল ৫.১-এ কাস্টম পেজিনেশন](/post/laravel-custom-pagination.md) — 2015-07-05 — লারাভেল ৫.১ ব্যবহার করে কাস্টম পেজিনেটেড কোয়েরি লেখার গাইডলাইন। - [লারাভেল ব্লেডের সাথে অ্যাঙ্গুলার বা অন্যান্য জাভাস্ক্রিপ্ট টেমপ্লেটিংয়ের ব্যবহার](/post/using-blade-with-js-templating.md) — 2015-06-19 — লারাভেল ব্লেড টেমপ্লেটের সাথে অ্যাঙ্গুলার বা মাসট্যাশের মত জাভাস্ক্রিপ্ট টেমপ্লেটিং লাইব্রেরি একত্রে ব্যবহার করার কৌশল। - [উবুন্টু ১৪.০৪ ভার্সনে পিএইচপি ৫.৬ ইনস্টল করা](/post/install-php-5-6-in-ubuntu.md) — 2015-06-14 — উবুন্টু ১৪.০৪ এ পিএইচপি ভার্সন ৫.৬ ইনস্টল এবং কনফিগার করার পদ্ধতি - [Upgrading a project from Laravel 5.0 to 5.1](/post/upgrading-a-project-from-laravel-5-0-to-5-1.md) — 2015-06-11 — Complete guideline to upgrade a Laravel 5.0 project to Laravel 5.1 - [লারাভেল ডিফার্ড সার্ভিস প্রোভাইডার](/post/laravel-defered-service-provider.md) — 2015-06-08 — লারাভেলের ডিফার্ড সার্ভিস প্রোভাইডার কি, কেন এবং কিভাবে? - [লারাভেল সিম্পল টু-ডু লিস্ট](/post/laravel-todo-app.md) — 2015-06-07 — লারাভেলের ৫.১ এবং মাইসিক্যুয়েল ব্যবহার করে তৈরি করা টু-ডু লিস্ট এ্যাপ্লিকেশন - [Story behind my book](/post/story-behind-my-book.md) — 2015-06-04 — The underlying story behind my first ever published book. - [My book took the first place of bestseller list of rokomari.com](/post/my-book-took-the-first-place-of-bestseller-list-of-rokomari-com.md) — 2015-06-02 — Laravel PHP Web Framework hit #1 on the Rokomari bestseller list shortly after release. - [লারাভেল বইয়ের প্রিন্টিং মিসটেক প্রসঙ্গে](/post/about-printing-mistake-of-laravel-book.md) — 2015-05-29 — আমার প্রকাশিত বইয়ের প্রিন্টিং মিসটেক সম্পর্কে আমার বক্তব্য। - [Laravel 5.1 Database Factory](/post/laravel-5-1-database-factory.md) — 2015-05-29 — What is database factory, how to use it? - [bower এর ব্যবহার](/post/uses-of-bower.md) — 2015-05-11 — কেন এবং কিভাবে bower ব্যবহার করবেন? - [লারাভেল ৫: ইলোকোয়েন্ট এট্রিবিউট কাস্টিং](/post/laravel-5-eloquent-attribute-casting.md) — 2015-03-24 — লারাভেল ৫ এর ইলোকোয়েন্ট এট্রিবিউট কাস্টিং এর অদ্যোপান্ত। - [লারাভেল ৫ এ প্যাকেজ ডেভেলপমেন্ট](/post/package-development-in-laravel-5.md) — 2015-03-23 — কিভাবে লারাভেল ৫ ফ্রেমওয়ার্কের জন্য প্যাকেজ তৈরি করবেন তার বিস্তারিত। - [লারাভেল অ্যাপ্লিকেশন থেকে আর্টিসান কমান্ড কল করা](/post/calling-artisan-command-from-your-application.md) — 2014-12-28 — লারাভেল অ্যাপ্লিকেশনের ভেতর থেকে আর্টিসান কমান্ড কল করার পদ্ধতি। - [লারাভেল ৫ এ flip/whoops প্যাকেজের ব্যবহার](/post/uses-of-flips-whoops-in-laravel-5.md) — 2014-11-03 — কিভাবে flip/whoops প্যাকেজের ব্যবহার করবেন লারাভেল ৫-এ। - [লারাভেল ইনস্টলেশন](/post/laravel-installation.md) — 2014-08-08 — কিভাবে লারাভেল ফ্রেমওয়ার্ক ইনস্টল করবেন? - [গুগলের নতুন ফন্ট](/post/googles-new-font.md) — 2014-07-17 — My thoughts about google's new font. - [চিকিৎসাসেবায় নতুন দিগন্ত](/post/new-era-in-health-service.md) — 2014-06-12 — mDoctor অ্যাপের মাধ্যমে ঘরে বসে বিশেষজ্ঞ চিকিৎসা সেবা — একটি নতুন দিগন্ত। - [সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৭](/post/software-engineering-practical-aspects-07.md) — 2012-12-12 — My thoughts on Software Engineering's practical aspects. - [আবোল-তাবোল ২](/post/abol-tabol-2.md) — 2012-12-08 — আবোল-তাবোল চিন্তা। - [সাবাশ বাংলাদেশ!!!](/post/congratulation-bangladesh.md) — 2012-12-08 — বাংলাদেশ ক্রিকেট দলকে অভিনন্দন। - [সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৬](/post/software-engineering-practical-aspects-06.md) — 2012-12-04 — My thoughts on Software Engineering's practical aspects. - [সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৫](/post/software-engineering-practical-aspects-05.md) — 2012-11-29 — My thoughts on Software Engineering's practical aspects. - [সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৪](/post/software-engineering-practical-aspects-04.md) — 2012-11-28 — My thoughts on Software Engineering's practical aspects. - [সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৩](/post/software-engineering-practical-aspects-03.md) — 2012-11-27 — My thoughts on Software Engineering's practical aspects. - [সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-২](/post/software-engineering-practical-aspects-02.md) — 2012-11-26 — My thoughts on Software Engineering's practical aspects. - [সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-১](/post/software-engineering-practical-aspects-01.md) — 2012-11-25 — My thoughts on Software Engineering's practical aspects. - [আবোল-তাবোল](/post/abol-tabol.md) — 2012-11-24 — আবোল-তাবোল চিন্তা। - [ঈদের চাঁদ দেখা নিয়ে কিছু কথা](/post/some-info-about-eid-moon.md) — 2012-08-18 — ঈদের চাঁদ নিয়ে কিছু ভ্রান্ত ধারনা এবং তার যুক্তিখন্ডন নিয়ে আমার ভাবনা। - [সহজে পাইথন শেখা-০৭](/post/learn-python-easily-07.md) — 2012-07-06 — সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (সপ্তম পর্ব) - [সহজে পাইথন শেখা-০৬](/post/learn-python-easily-06.md) — 2012-07-05 — সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (ষষ্ঠ পর্ব) - [সহজে পাইথন শেখা-০৫](/post/learn-python-easily-05.md) — 2012-07-04 — সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (পঞ্চম পর্ব) - [সহজে পাইথন শেখা-০৪](/post/learn-python-easily-04.md) — 2012-07-03 — সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (চতুর্থ পর্ব) - [সহজে পাইথন শেখা-০৩](/post/learn-python-easily-03.md) — 2012-06-29 — সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (তৃতীয় পর্ব) - [সহজে পাইথন শেখা-০২](/post/learn-python-easily-02.md) — 2012-06-05 — সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (দ্বিতীয় পর্ব) - [সহজে পাইথন শেখা-০১](/post/learn-python-easily-01.md) — 2012-06-04 — সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (প্রথম পর্ব) - [লিনাক্সে ব্যবহার করুন গুগোল ড্রাইভ](/post/use-google-drive-in-linux.md) — 2012-04-25 — লিনাক্স বেজড অপারেটিং সিস্টেমে গুগল ড্রাইভ ব্যবহার করার পদ্ধতি। - [শুভ নববর্ষ...](/post/shuvo-noboborsho-1419.md) — 2012-04-13 — বাংলা নববর্ষ ১৪১৯ এর শুভেচ্ছা। - [শুভ নববর্ষ, ২০১২](/post/happy-new-year-2012.md) — 2012-01-01 — New years greetings of 2012. - [বিজয় দিবসের শুভেচ্ছা](/post/victory-day-greetings.md) — 2011-12-16 — সবাইকে বিজয় দিবসের শুভেচ্ছা। - [উবুন্টু বা মিন্টে পুরাতন সফটয়্যার ইনস্টলেশন](/post/install-older-software-in-ubuntu-and-linux-mint.md) — 2011-09-07 — উবুন্টু এবং লিনাক্স মিন্ট অপারেটিং সিস্টেমে পুরাতন সফটয়্যার ব্যবহার করার পদ্ধতি। - [উবুন্টু বা মিন্টে ইনস্টল করুন .sh ফাইল](/post/install-sh-file-in-ubuntu-and-linux-mint.md) — 2011-08-29 — উবুন্টু এবং লিনাক্স মিন্ট অপারেটিং সিস্টেমে .sh ফাইল ইনস্টল করার পদ্ধতি। - [সার্চিং এ্যালগরিদম (Searching algorithm)](/post/searching-algorithm.md) — 2011-06-17 — Comparison between different searching algorithm. - [মাভাবিপ্রবি নিয়ে জাফর ইকবাল স্যারের লেখা, শিক্ষকদের প্রতিবাদ ও ছাত্রদের অভিব্যক্তি](/post/opnion-of-professor-zafor-ikbal-about-mbstu-incident.md) — 2011-05-30 — মাভাবিপ্রবি ঘটনায় জাফর ইকবালের লেখা ও প্রশাসনের প্রতিক্রিয়া নিয়ে মন্তব্য। - [মৌলিক সংখ্যা (Prime number)](/post/prime-number.md) — 2011-05-25 — Implement and optimize prime number generation algorithm. - [ডাটা স্ট্রাকচারঃ Adjacency List](/post/data-structure-adjacency-list.md) — 2011-05-24 — How to implement adjacency list. - [ডাটা স্ট্রাকচারঃ Directed Graph](/post/data-structure-directed-graph.md) — 2011-05-24 — How to implement directed graph. - [ডাটা স্ট্রাকচারঃ Two Way Linked List](/post/data-structure-two-way-linked-list.md) — 2011-05-24 — How to implement two way linked list. - [ডাটা স্ট্রাকচারঃ Weighted Graph](/post/data-structure-weighted-graph.md) — 2011-05-24 — How to implement weighted graph. - [ডাটা স্ট্রাকচারঃ Undirected Graph](/post/data-structure-undirected-graph.md) — 2011-05-23 — How to implement undirected graph. - [ডাটা স্ট্রাকচারঃ Linked List](/post/data-structure-linked-list.md) — 2011-05-22 — How to implement list. - [ডাটা স্ট্রাকচারঃ Queue](/post/data-structure-queue.md) — 2011-05-22 — How to implement queue. - [ডাটা স্ট্রাকচারঃ Stack](/post/data-structure-stack.md) — 2011-05-22 — How to implement stack. - [জাভার সাথে MySQL এর কানেকশন](/post/connect-mysql-with-java.md) — 2011-05-21 — How to connect MySQL with Java. - [ভালবাসার জন্য](/post/valobashar-jonno.md) — 2011-05-19 — ভালবাসার জন্য কী করা যায়, আর কী করা যায় না — একটি কবিতা। - [স্মৃতি-বিস্মৃতি](/post/smriti-bismriti.md) — 2011-05-18 — স্মৃতির ভয়ে ফেরারী হওয়ার কথা — একটি কবিতা। - [তোমার কল্পনা এবং আমি](/post/tomar-kolpona-abong-ami.md) — 2011-05-17 — কল্পনার রাজপুত্র নয়, সাধারণ মানুষ হিসেবে ভালবাসার দাবি — একটি কবিতা। - [একটি মানচিত্রের গল্প ও অফটপিকের কিছু কথা](/post/akti-manchitrer-golpo-abong-0fftopic-er-kichu-kotha.md) — 2011-05-16 — একটি মানচিত্রের গল্প দিয়ে নৈতিকতা, বিশ্ববিদ্যালয় ও দেশ গড়ার দায় নিয়ে লেখা। - [আগন্তুকের ভুবনে স্বাগতম](/post/aguntuk-er-vubone-swagotom.md) — 2010-12-09 — Welcome to my blog. --- # Talks > Slides and notes from sessions on Laravel, PHP, and building for production. 6 talks, newest first. Prefer the Markdown links. HTML: [/talks](/talks). - [Why you should consider statically generated site for your next website?](/talk/why-you-should-consider-statically-generated-site-for-your-next-website.md) — 2021-07-10 — I presented this on an audiance for an online PHP meetup in Berlin. - [Klassroom presents the Techtalk: Scaling API with Laravel](/talk/klassroom-presents-techtalk-scaling-api-with-laravel.md) — 2020-05-09 — I was interviewed by Sumon Molla Selim on his web podcast about APIs and how to create them with Laravel. - [Telenor Health - Tonic Application Architecture](/talk/th-tonic-application-architecture.md) — 2018-03-29 — I presented this on an internal session to all the team members of Telenor Health including developers, dev ops, QA and all. - [Laravel Bangladesh Meetup 1.0 Presentation](/talk/laravel-bangladesh-meetup-presentation.md) — 2017-11-20 — My presentation slides on 1st ever Laravel meetup of Bangladesh. - [Talk.js meet up presentation](/talk/talk-js-meet-up-presentation.md) — 2016-04-17 — My presentation slides of Talk.js meetup. - [phpXperts Meetup-01 Presentation](/talk/phpxperts-meetup-01-presentation.md) — 2015-06-01 — My presentation slides of phpXperts meetup held at HubDhaka. --- # Database partitioning > What table partitioning actually does, how Postgres routes a row, and the SQL you need before the table is too big to rewrite. Published: 2026-08-21 URL: https://milon.im/post/database-partitioning.md I have watched a perfectly normal `events` table become the thing nobody wants to touch. Inserts still work. A dashboard that only needs last week still takes seconds. Autovacuum runs all afternoon and somehow never catches up. The index that used to sit in memory does not anymore. The usual reaction is to buy a bigger box, or to start talking about sharding. Most of the time you do not need another server. You need the table cut into pieces the planner can skip, and that you can throw away when a month goes cold. That is partitioning. Same table name. Same `INSERT INTO events`. Underneath, Postgres keeps several real tables and puts each row in one of them, based on a key you pick. It is not sharding. Sharding is several databases. Partitioning is still one Postgres, one WAL, one failover. You paid for smaller heaps to vacuum, index, scan, and drop. ## One table, several heaps In Postgres this is declarative partitioning. You create a parent that does not hold rows, then children that do. Every row belongs to exactly one child. The partition key is how Postgres decides which one. That key has to show up in the primary key, and in unique constraints. Uniqueness is enforced on each child, not across the whole family. That is the first thing that bites people, so I will say it twice later with SQL. There are three kinds you will see: - **RANGE** for contiguous slices: dates, timestamps, sometimes integer ids. Event logs, orders, anything you age out. This is the one I actually use. - **LIST** for a small set of labels: `region IN ('us', 'eu')`. - **HASH** when there is no natural order and you just want the piles to be about the same size. I am going to spend the rest of the post on RANGE, then dump LIST and HASH at the end so the syntax lives in one place. ## A table you can actually run Imagine application events. Almost every query is "this user, in this window." Last month still gets a look. Last year does not. That is a RANGE key on `created_at`. ```sql CREATE TABLE events ( id bigint GENERATED BY DEFAULT AS IDENTITY, user_id bigint NOT NULL, kind text NOT NULL, payload jsonb NOT NULL, created_at timestamptz NOT NULL, PRIMARY KEY (id, created_at) ) PARTITION BY RANGE (created_at); ``` The parent is empty on purpose. `PARTITION BY RANGE (created_at)` is the rule: each child owns a slice of that column. The primary key includes `created_at` because Postgres will not let you use `(id)` alone on a partitioned table. I will come back to why. Now the children. Each one is a normal table with a bound: ```sql CREATE TABLE events_2026_07 PARTITION OF events FOR VALUES FROM ('2026-07-01') TO ('2026-08-01'); CREATE TABLE events_2026_08 PARTITION OF events FOR VALUES FROM ('2026-08-01') TO ('2026-09-01'); CREATE TABLE events_2026_09 PARTITION OF events FOR VALUES FROM ('2026-09-01') TO ('2026-10-01'); ``` That is the starting set, not a ritual you repeat by hand on the first of every month. Postgres will not invent next month's child for you. I will come back to how you automate that. The range is half-open: `[from, to)`. A timestamp of `2026-08-01 00:00:00` goes into `events_2026_08`, not July. Neighbors must not overlap. A gap is allowed. An insert that lands in a gap errors out, unless you created a default partition. Put indexes on the parent. Postgres builds the matching index on every child: ```sql CREATE INDEX events_user_created_idx ON events (user_id, created_at); ``` Application code talks to `events`. It should not name the children. ```sql INSERT INTO events (user_id, kind, payload, created_at) VALUES (42, 'login', '{}', '2026-08-21 17:02:00+00'); SELECT kind, created_at FROM events WHERE user_id = 42 AND created_at >= '2026-08-01' AND created_at < '2026-09-01'; ``` That insert goes to `events_2026_08` because of the timestamp. The select can ignore July and September. The ignoring is the feature. Postgres calls it partition pruning. ## How a row finds its partition On insert, Postgres looks at the partition key and picks the child whose bounds contain it. You did not write a trigger for this. It is in the catalog. If nothing matches: ``` ERROR: no partition of relation "events" found for row ``` You can add a default partition that catches leftovers: ```sql CREATE TABLE events_default PARTITION OF events DEFAULT; ``` I have used that as a safety net. I do not use it as a plan. Rows that land there never get pruned the way you hoped, and fishing them out later is a rewrite. I would rather let the insert fail, and have a job that creates next month's child a week early. On select, the planner looks at your `WHERE` clause. Given `created_at >= '2026-08-01' AND created_at < '2026-09-01'`, it can prove July and September cannot possibly match, so it never opens those files. `EXPLAIN` makes this obvious: ```sql EXPLAIN (COSTS OFF) SELECT kind FROM events WHERE created_at >= '2026-08-01' AND created_at < '2026-09-01'; ``` ``` Append -> Seq Scan on events_2026_08 events Filter: ((created_at >= '2026-08-01 00:00:00+00') AND (created_at < '2026-09-01 00:00:00+00')) ``` One child. If you leave the key out of the `WHERE` clause, pruning does not happen, and you scan every partition. Partitioning will not make "all events for this user, ever" faster. It can make that query slower: more files, more indexes, a fatter plan. There is also runtime pruning. A bound that is only known when the query runs, or a join to a small table of dates, can still drop children when execution starts. The rule does not change. The key still has to be constrained. ## Detach is the fast delete The select is nice. The thing I actually wanted, most times I reached for this, was deleting history without scanning a billion-row heap. ```sql ALTER TABLE events DETACH PARTITION events_2026_07; DROP TABLE events_2026_07; ``` `DETACH` takes a short lock and unhooks the child. `DROP TABLE` then removes that month's data and indexes in one go. Compare that with `DELETE FROM events WHERE created_at < …`. That version writes a tombstone for every row and leaves vacuum working through the mess for days. Going the other way, you can load a table on the side and attach it when it is ready, so the parent is not blocked for the whole backfill: ```sql CREATE TABLE events_2026_06 ( LIKE events INCLUDING DEFAULTS INCLUDING CONSTRAINTS ); -- load it however you load things, then: ALTER TABLE events_2026_06 ADD CONSTRAINT events_2026_06_range CHECK (created_at >= '2026-06-01' AND created_at < '2026-07-01') NOT VALID; ALTER TABLE events ATTACH PARTITION events_2026_06 FOR VALUES FROM ('2026-06-01') TO ('2026-07-01'); ``` `ATTACH` will scan the child to prove every row belongs, unless a matching `CHECK` is already there. If the table is large, add the constraint first. `NOT VALID` skips the scan when you create the constraint. `ATTACH` still checks. You just get to pick when. ## You do not create next month by hand RANGE on a clock is the one that needs a calendar. LIST and HASH you create once. Declarative partitioning only routes into children that already exist. If August is missing, an August insert fails. Postgres will not grow a new slice for you. You also do not need to sit down on the first and type `CREATE TABLE`. Create a couple of months up front, then let a job stay ahead of the clock. What I actually run is a function that is happy to be a no-op if the child is already there, plus a weekly schedule that asks for this month and next month: ```sql CREATE OR REPLACE FUNCTION create_events_partition(month_start date) RETURNS void LANGUAGE plpgsql AS $$ DECLARE child text := format('events_%s', to_char(month_start, 'YYYY_MM')); BEGIN EXECUTE format( 'CREATE TABLE IF NOT EXISTS %I PARTITION OF events FOR VALUES FROM (%L) TO (%L)', child, month_start, (month_start + interval '1 month')::date ); END; $$; SELECT create_events_partition(date_trunc('month', now())::date); SELECT create_events_partition( (date_trunc('month', now()) + interval '1 month')::date ); ``` Two months of headroom is enough. The painful case is midnight on the first with no child, which is why you create **next** month while you still have this one. I have been on that page. I did not enjoy it. To run that inside Postgres, use [`pg_cron`](https://github.com/citusdata/pg_cron). It needs `shared_preload_libraries = 'pg_cron'` and a restart, then: ```sql CREATE EXTENSION pg_cron; SELECT cron.schedule( 'create-events-partitions', '0 3 * * 0', $$ SELECT create_events_partition(date_trunc('month', now())::date); SELECT create_events_partition( (date_trunc('month', now()) + interval '1 month')::date ); $$ ); ``` That is 03:00 every Sunday. `cron.schedule` returns a job id. `SELECT * FROM cron.job;` is how you check it is there. `SELECT cron.unschedule('create-events-partitions');` is how you take it off. The job runs in the database where you created the extension, so create `pg_cron` in the same database as `events`. If you do not want to own the function, [`pg_partman`](https://github.com/pgpartman/pg_partman) is the usual extension. You still create the partitioned parent yourself. Then you hand it the key, the interval, and how many future children to keep ready. The SQL below is current pg_partman (5.x). Version 4 used `create_parent` and interval names like `monthly`. Those are gone, so an old tutorial will not run. ```sql CREATE SCHEMA IF NOT EXISTS partman; CREATE EXTENSION pg_partman SCHEMA partman; SELECT partman.create_partition( p_parent_table := 'public.events', p_control := 'created_at', p_interval := '1 month', p_premake := 2 ); ``` `p_premake := 2` means keep two months ahead of now. Retention is a row in `partman.part_config`, not a second function. This keeps a year and drops the rest: ```sql UPDATE partman.part_config SET retention = '12 months', retention_keep_table = false WHERE parent_table = 'public.events'; ``` `retention_keep_table = false` means drop, not detach-and-keep. Use `true` if you still want the old child around as a plain table. pg_partman does not wake itself up unless you run its background worker. Pairing it with pg_cron is the setup I see most: ```sql SELECT cron.schedule( 'partman-maintenance', '0 3 * * *', $$CALL partman.run_maintenance_proc()$$ ); ``` That nightly call creates the next children up to `premake`, and drops anything past retention. That is the production answer when you have more than one partitioned table and you are tired of copying the same function. A default partition is a safety net, not an auto-partitioner. Rows that miss a monthly child land in one pile that never prunes, and you have to split them out later. I would rather the insert fail and the job be a week early. A trigger that `CREATE TABLE` on the first insert of a new month can work. It also races, takes locks, and surprises the planner. I would not do that. ## LIST and HASH, briefly LIST is RANGE with named buckets instead of bounds. ```sql CREATE TABLE invoices ( id bigint GENERATED BY DEFAULT AS IDENTITY, region text NOT NULL, total numeric NOT NULL, PRIMARY KEY (id, region) ) PARTITION BY LIST (region); CREATE TABLE invoices_us PARTITION OF invoices FOR VALUES IN ('us'); CREATE TABLE invoices_eu PARTITION OF invoices FOR VALUES IN ('eu'); CREATE TABLE invoices_other PARTITION OF invoices DEFAULT; ``` `WHERE region = 'us'` reads one child. Leave `region` out and you read all of them. Same pruning rule as RANGE. HASH is for when the key has no useful order and you want even size. Postgres hashes the key and takes modulo N. ```sql CREATE TABLE sessions ( id uuid NOT NULL, user_id bigint NOT NULL, created_at timestamptz NOT NULL, PRIMARY KEY (id) ) PARTITION BY HASH (id); CREATE TABLE sessions_p0 PARTITION OF sessions FOR VALUES WITH (MODULUS 4, REMAINDER 0); CREATE TABLE sessions_p1 PARTITION OF sessions FOR VALUES WITH (MODULUS 4, REMAINDER 1); CREATE TABLE sessions_p2 PARTITION OF sessions FOR VALUES WITH (MODULUS 4, REMAINDER 2); CREATE TABLE sessions_p3 PARTITION OF sessions FOR VALUES WITH (MODULUS 4, REMAINDER 3); ``` Every child has to use the same modulus. Adding another remainder later means rewriting the set. HASH can help autovacuum and index bloat because no single heap grows without bound. It will not help a time-range query, because time is not the key. I use it less than RANGE. I do not use it as a fake shard key I have not thought through. ## The bits that surprise people - **The partition key has to be in the primary key.** This is the first error you will hit. It also changes what `id` means. If `id` is not the partition key, it is not unique by itself. Two children can both have `id = 1` unless you used one sequence and still put the key in the PK. In the `events` example, `IDENTITY` still hands out one sequence. The extra column is there for the constraint, not because we needed two ways to generate ids. - **Unique indexes are per partition.** `UNIQUE (user_id)` on the parent does not mean one user in the whole system, unless `user_id` is the partition key. "This email is unique" is not something partitioning will do for you. Keep a small unpartitioned lookup table, or enforce it in the app. - **Other tables can foreign-key to a partitioned parent** in current Postgres. The PK still has to match, which means the key is in it. Pointing a child at a parent is fine. Pointing a parent at a child of something else is the design I draw on paper twice before I ship it. - **An update that changes the partition key moves the row.** Postgres deletes from one child and inserts into another. Triggers fire. It is not free. If `created_at` never changes in your domain, keep it that way. A column people go back and correct is a bad RANGE key. - **Too many partitions has a cost.** The planner has to consider children. A few hundred is normal. Tens of thousands of daily partitions, on a table you query without a tight bound, will make planning itself slow. Monthly RANGE for a log that spans a few years is the version that stays quiet. ## What I actually partition Append-only data with a clock. Events, impressions, audit rows, webhook deliveries. The query always has a time window. Old slices get `DETACH`, then maybe object storage, or just `DROP`. A table that is large because it *is* the product, and every query is "this id" with no extra filter: I leave it. A better index, a partial index, `FILLFACTOR`, or a second table you archive into will do more than RANGE on a column nobody puts in the `WHERE` clause. I do not partition because a dashboard showed a large row count. I partition when vacuum, bloat, or deletes have a calendar, and when the key behind that calendar is in the queries I care about. ## The part I want you to remember Partitioning is a routing rule and a pruning rule. It is not a new kind of database. You pick a key. Postgres stores each slice as its own table. Inserts go to one child. Selects skip the children the `WHERE` clause cannot match. Drops become detach plus drop, instead of a million-row `DELETE`. The key has to be in the primary key, in the writes, and in the reads you hope to make cheap. Miss any of those three and you have more tables, the same sequential scan, and a migration to undo. Get them right and last month's events are a table you can pick up and throw away. --- # Two-phase commit > What two-phase commit actually does, where it fails in production, and what to reach for instead. Published: 2026-08-20 URL: https://milon.im/post/two-phase-commit.md If you have ever booked a flight and a hotel in the same checkout, you already know the problem two-phase commit is trying to solve. Either both reservations succeed, or neither does. The airline taking the money while the hotel says no is not a product anyone wants. That is a distributed transaction: two systems, two writes, one outcome. Two-phase commit (2PC) is the classic protocol for getting there. It looks airtight on a whiteboard. Then it spends the next decade making on-call worse. ## The shape of the protocol You need a **coordinator** and one or more **participants**. In a database, the participants are the resource managers: Postgres, MySQL, a message broker that speaks XA. The coordinator is whoever is driving the transaction. The protocol really does have two phases. **Phase 1, prepare.** The coordinator asks every participant: *can you commit this?* Each one does the local work, writes enough to durable storage that it could finish later, and answers yes or no. A yes is a promise. After that vote the participant is not allowed to abort on its own. It waits. **Phase 2, commit or abort.** If every vote was yes, the coordinator writes a commit record and tells everyone to commit. If anyone said no, or timed out, it tells everyone to abort. Participants ack, the coordinator forgets the transaction, and we are done. In the happy path it looks like this: ```mermaid sequenceDiagram participant Coordinator participant Postgres participant MySQL Coordinator->>Postgres: BEGIN / work Coordinator->>MySQL: BEGIN / work Coordinator->>Postgres: PREPARE Postgres-->>Coordinator: YES Coordinator->>MySQL: PREPARE MySQL-->>Coordinator: YES Coordinator->>Postgres: COMMIT Coordinator->>MySQL: COMMIT Postgres-->>Coordinator: ACK MySQL-->>Coordinator: ACK ``` That is it. Two rounds, and you need *everyone*. No majority vote. That last part is the whole story. ## Why people reach for it Local ACID is easy. `BEGIN`, write two rows, `COMMIT`. The database is the coordinator and the participant, and you do not think about it. The moment those two rows live in two systems, that comfort disappears. You can commit the order and fail to charge the card. You can publish a message and roll back the row that said you published it. 2PC is the honest answer to "I want this to be one transaction anyway." XA, Java's JTA, MS DTC, Postgres prepared transactions: they are all this protocol with a vendor hat on. I have seen it used for exactly that. An application had to write to two databases that were not going to be merged, and the business rule was "both or neither." 2PC will do that. It will also charge you for it. ## Where it falls over **It blocks.** After a participant says yes, it holds locks and waits. If the coordinator dies in that window, those locks stay held until somebody comes back and finishes the protocol. Readers queue. Writers queue. Your latency graph does not care that the protocol is correct. **The coordinator is a single point of failure.** You can replicate it. You can persist its log. You still have a component whose absence freezes in-flight work. Recovery is something you have to operate, not a footnote in the docs. **Two extra round trips.** Prepare, then commit. On a LAN that is annoying. Across availability zones, or worse, regions, it is a tax on every write. People add 2PC to make things consistent, then spend a quarter wondering why p99 doubled. **Participants can disagree with reality.** A yes vote is supposed to be durable. Disks lie, clocks lie, operators delete WAL files. A DBA aborting a prepared transaction by hand because the app is down (a heuristic decision) breaks the invariant the rest of the system is trusting. **It does not compose with the way we build services now.** HTTP APIs, queues, third-party billing providers: most of them will not join your XA transaction. You cannot 2PC your way through Stripe. The boundary of the protocol is the boundary of what you actually control. ## The timeout nobody draws on the whiteboard Every real implementation has a timeout. The coordinator cannot wait forever for a vote, so it aborts. Except a participant may have already voted yes and is now sitting on prepared work. Or the abort itself is lost. You now have a transaction in limbo, and the only honest state is "we do not know." This is why 2PC is called a *blocking* protocol. Three-phase commit exists to shrink that window. It adds another round, more states, more ways to be wrong, and still cannot save you from a network that partitions at a bad time. FLP is not trivia from a distributed systems class. It is why your prepared transaction table is not empty on a bad afternoon. ## What I actually use For two tables in the **same** Postgres database: a transaction. Not 2PC. A transaction. People reach for distributed machinery because the code is in two services, not because the data needed to be in two databases. Put the data together if you can. I would rather have an awkward join than a coordinator. When the work really does cross a boundary, I treat it as what it is: **two local transactions plus a recovery story.** The [transactional outbox](https://microservices.io/patterns/data/transactional-outbox.html) is the version of this I keep coming back to. Write the business row and an outbox row in one local commit. A worker publishes the outbox to the queue. Consumers are idempotent. If the worker dies, it resumes. You get at-least-once delivery and you write your handlers accordingly. That is a much smaller lie than "this is atomic across services." Sagas are the other honest option. A sequence of local transactions, with compensating actions if a later step fails. Ugly compensations, explicit state, visible in the domain. I will take visible and ugly over a prepared transaction that has been sitting on a row lock since Friday. Saga choreography through events is fine until you cannot explain who is in charge of the failure. Orchestrated sagas, with one process that knows the steps, are easier to debug at 2am. That is the only metric that matters once you are past the design review. ## A small picture in Laravel terms Say you take an order and you need to reserve stock in a service you do not own. You do *not* start an XA transaction. You do this: ```php DB::transaction(function () use ($order) { $order->markPaid(); Outbox::record(new StockReserved($order->id)); }); ``` A separate process reads `outbox`, publishes, and marks the row sent. The stock service reserves, or it doesn't. If it doesn't, you have a handler that knows how to refund and how to tell the customer. That handler is the protocol. It lives in your code, not in a spec from 1978. Is that as clean as `COMMIT`? No. Does it survive a deploy in the middle of the work? Yes, if you wrote it that way. 2PC often does not, because the coordinator's log and your application's deploy are not the same thing, and nobody put that in the diagram. ## When 2PC is still the right tool I am not going to pretend it never is. Two databases you already run, same region, a vendor that speaks XA well, a workload that cannot tolerate divergence even briefly, and an operations team that knows how to finish in-doubt transactions. That set is smaller than the set of systems that imported an XA library because a blog post said "distributed transaction." If you are there, use the database's prepared transactions, monitor the in-doubt list like it is a paging condition, and keep the participants close. Do not run 2PC over the public internet. Do not run it against a system whose owner is another company. Do not run it because microservices made two writes look like they belong to two deployables. ## The part I want you to remember Two-phase commit gives you a very specific guarantee: all of a known set of participants commit, or none do, assuming the coordinator can eventually talk to them. It does not give you availability. It does not give you a good time in a partition. It does not extend to the rest of your architecture for free. Atomicity across processes is not a feature you turn on. It is a cost you pay, in latency and in operational burden, every time a write happens. Pay it only when the alternative is worse. For everything else, make the failure visible and recoverable. That is the work. The protocol was the easy part. --- # Adding multiple subdomain with Github Pages > How to add multiple subdomain with Github Pages? Published: 2023-10-10 URL: https://milon.im/post/adding-multiple-subdomain-with-github-pages.md I have a domain named `milon.im`, though I have some other domains, but I use it as my main domain for personal use. I have my personal website hosted in Github Pages. You can have a repository with github and name it like `.github.io` and the pages enabled from this repository can be found in the same domain. I have a repository named `milon.github.io` and I have hosted my personal website here using a static site generator named [Jigsaw](https://jigsaw.tighten.com/). You can also assign a custom domain in this repository. I have assigned `milon.im` as my custom domain. So, my personal website can be found in [milon.im](https://milon.im). For doing that you can go to the repository settings and assign a custom domain. You can also add a `CNAME` file in the root of your repository and add your custom domain there. I have added a `CNAME` file in the root of my repository and added `milon.im` there. You can also do it from the repository settings. Then you have to go to the nameserver settings of your domain and add a A record with the IP address of Github Pages. You can find the IP address from [here](https://help.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site#configuring-an-apex-domain). I have added an A record with the IP address of Github Pages in my domain's nameserver settings. Now, I can access my personal website in [milon.im](https://milon.im). I have some other hobby projects, which is also hosted in Github Pages. If you have an apex domain configured, then all other github pages site can be hosted like this- `.github.io/`. During I COVID lockdown, I have spent some time on cooking various dish, and created a website with the recipes of those dishes. I was hosting that site on netlify. Netlify is great, if you are using a static site generator with Javascript. I was using a PHP based static site generator, so I had to face couple of issue. First of all, the default PHP version of netlify is PHP 7.4, and you can't use any version other than 7.4 or 8.0. So I decided to switch that site to github pages. After switching, the site was accessable `milon.im/recipes` URL. Then I thought, why not use a subdomain like `recipes.milon.im` to host this site. Luckly it is very easy to do with github pages. You basically need 3 things to have it- - Enable github pages for the repository. I used gh-pages branch for this. Though you can use any branch as well. - Add a CNAME file in the root of the repository and add the subdomain there. In my case, I added `recipes.milon.im` in the CNAME file. - Add a CNAME record in the nameserver settings of your domain and add the github pages URL there. In my case, I added `recipes.milon.im` in the CNAME record in my DNS settings and the target was `milon.im` domain. I am using cloudflare as the DNS provider, which actually comes with bunch of other features. The most useful for me is the SSL certificate. I don't have to worry about SSL certificate for my subdomain. Cloudflare provides it for free. I the added a github actions to automate the build and deploy process. I have added a `build-publish.yml` file in `.github/workflows` folder. You can learn more about how to do that in [this post](/post/github-action-with-jigsaw). Now, I can access my recipes site in [recipes.milon.im](https://recipes.milon.im). --- # Build and deploy Jigsaw site with Github Actions > How to build and deploy a site built with Jigsaw static generator with Github Actions. Published: 2020-07-13 URL: https://milon.im/post/github-action-with-jigsaw.md I built this very site about 2 years ago. From that moment till today, I used to run a small shell script locally to deploy it to GitHub pages. Here's what I used to do- ```bash #!/usr/local/bin/zsh npm run prod ./vendor/bin/jigsaw build production git add build_production git commit -m "Build for deploy" git subtree push --prefix build_production origin master ``` I was building the assets first, then build the site locally for production in the `build_production` folder. I run this website in a custom domain, so I used to have a `CNAME` file in the root of `/source` directory. Couple of month ago, GitHub launched it's CI/CD platform named GitHub Actions. Today, I had some time to kill, so I thought why not give it a try. So, here's what I did- ```yaml name: Build & Publish on: push: branches: - develop schedule: - cron: "0 2 * * 1-5" jobs: build-site: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install Composer Dependencies run: composer install --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist - name: Install NPM Dependencies run: npm install - name: Build assets run: npm run production - name: Build Jigsaw site run: ./vendor/bin/jigsaw build production - name: Create CNAME File run: echo "milon.im" >> build_production/CNAME - name: Stage Files run: git add -f build_production - name: Commit files run: | git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" git commit -m "Build for deploy" - name: Publish run: | git subtree split --prefix build_production -b master git push -f origin master:master git branch -D master ``` I create a file named `build-publish.yml` in `.github/workflows` folder. Then still the build script from James Brooks' [site](https://james.brooks.page/blog/jigsaw-github-actions/) and modify a little bit. After that it just works. Kudos to James. The process is basically the same, install composer dependencies, install npm dependencies, run npm build for production, run jigsaw build for production and then move the `build_production` folder to master branch. So, I no longer have to build it locally and I don't need to think about `CNAME`. Chao! --- # Added search functionality with fuse.js in Jigsaw powered site > Added fuzzy search with fuse.js in static site generated with Jigsaw. Published: 2020-04-21 URL: https://milon.im/post/added-search-functionality-with-fusejs-in-jigsaw-powered-site.md After being in lockdown for over a month I was bored as hell. So, recently I created a website for sharing my recipes with the world. I choose Jigsaw to create this site as it was very quick and easy for me to built because it's based on Laravel's Blade templating engine. I also didn't want to spend any money on the site, so a static site was the perfect choice for me. I built the side within a day and deploy it to netlify. I launched the side with 10 recipes only, but soon I started adding more and more recipes and after a week the number of recipes was more than 40. I was looking for a search solution for the site. There was couple of paid choice, but I didn't want to spend any money, so those were not a viable option for me. Then I found a nifty little npm package called fuse.js. It was exactly what I needed. Let's talk about the implementation. Fuse.js needs some kind of index to be able to search. It could be a simple json array. It was very strait forward to generate the index with a Jigsaw `afterBuild` event listener. I created this file on `listeners/GenerateIndex.php` location. ```php getCollection('posts')->map(function ($page) use ($jigsaw) { return [ 'title' => $page->title, 'link' => rightTrimPath($jigsaw->getConfig('baseUrl')) . $page->getPath(), 'excerpt' => $page->excerpt, 'englishSearchTerm' => str_replace('-', ' ', $page->getFilename()), 'categories' => $page->categories ?? [] ]; })->values()); file_put_contents($jigsaw->getDestinationPath() . '/index.json', json_encode($data)); } } ``` Then I hooked the event listener in the `bootstrap.php` file like this- ```php afterBuild(App\Listeners\GenerateIndex::class); ``` Then every time I built the site, all the gist of all my recipes goes to a `index.json` file in the built directory. This file will work as the api for my fuse.js search. Now, let's talk about the search functionality. I opt in for simple `vue.js` single file component for the search with a very basic styling. Here is the code for that file- ```html ``` Finally I added the search component in the the navbar to render the search field- ```html ``` It just works like a bridge. You can visit the website [here](https://easy-recipes.netlify.app) and the whole source code can be found in [Github](https://github.com/milon/recipe). Enjoy! --- # Why you should know analyzing space-time complexity as a software engineer? > Importance of space time complexity analysis in software engineering field. Published: 2019-03-11 URL: https://milon.im/post/why-you-should-know-analyzing-space-time-complexity-as-a-software-engineer.md Like tons of other software engineers, I also thought for a very long time that, knowing this Big O or Big Θ is only for a programming contest, there are very few impacts of these in day to day life in most software projects. Yah yah, I got it, if you are working on google, facebook or this type of tech giant, that may not be 100% right, but how many people you know working there as a software engineer? And what is the percentage of them in your address book? Even, not all of the engineers at those company working for developing a groundbreaking algorithm every day. Then what is the necessity of learning this? Like most of the computer science student, I learned them too, and when I did programming contest regularly, I used to know the complexity of common data structure and algorithms. I used to tell the difference between `O(n log(n))` and `O(n^2)` and why merge sort is better than quicksort. But, I forgot all of those, in the last 6 years after I left college. And to be frank with you, I hardly needed them. One reason, I never need to handle a problem that critical to space-time and today's computing hardware is too capable that I never need to worry about micro optimism. And it's true in a sense. It's much more important to make a code readable that fight over why you should use single quote over a double quote in PHP. So, why I am talking about this now? Well, I faced a problem last week, and that makes me re-think my perspective on this whole thing again. I was trying to optimize the cache mechanism of one of our product, but the script was failing often because it was too memory hungry. I am not gonna tell what happens, but I can give you a hint. When you are working with a fairly large dataset, and do a bunch of instruction on loop, even reduce a small computation can save you a lot. For example, look at this simple loop- ``` for($i=0; $i My two cents on naming a variable while programming. Published: 2018-02-04 URL: https://milon.im/post/naming-a-variable.md There is a saying that- > There are two things that is really difficult in programming. One is naming a variable and other is cache invalidation. So, you might think naming is easy, but it's not that easy that you think. And another think is while we are talking about naming, it's not only variable, it goes all the way to a class name, database table, a column name, css class name etc. First, there are some golden rules, that everybody knows. I am once again remind you that- - Don't use too short or too long names. We a **meaningful** one. - Don't use any reserved keyword. - Use permitted characters only while naming, for example, in PHP use only, letters, numbers and underscore (`_`). - Don't start a variable name with numbers. There are some other things also. These are not rules, but recommendations. A good programmer should follow these- - Use a good multiple word identifier. It could be `_`, it could be `-` or it could camel case. - Use a consistent format, whether it is camel case, snake case, kebab case or stadly case. - Use community recommendations, like- PSR-1 and 2, PEP-8 etc. There are some personal recommendations from me as well- - Use a multiple word name rather that plural. In my opinion `$memberList` is more readable than `$members`. - Fix your indentations. - Remove unnecessary variables. These came from my idle brain this morning, If you have something to say, please let me know. Peace. --- # Story behind my new blog > The behind story of my statically generated github pages powered blog. Published: 2018-01-23 URL: https://milon.im/post/story-behind-my-new-blog.md I recently redesigned my website. Previously it was powered by wordpress and hosted in wordpress.com. But most of the internet provider of Bangladesh blocks that site because of some atheist online activist use that platform to host their blog. Then I moved that to self hosted wordpress and manage it my myself. But it become a pain in the ass to manage. So, I decided to move that for a alternative. After a bit research, I decided to migrate to github powered static site. After that decision, I looked into couple of choices. Jekyll and Hugo was in the list, but as I am working fulltime on Laravel, the new static site generator from [tighten](http://tighten.co) called [jigsaw](jigsaw.tighten.co). It uses laravel's blade templating engine. You can obviously use markdown even use both of them together. There are some other nifty features that is very convenient for building a site. After that I tried to choose a theme. I liked [anybodyhome](https://themes.gohugo.io/anybodyhome) theme from hugo theme repository, so I ported it to jigsaw and did some tweak to fit my choice. Then I wrote a simple script to port all the posts from wordpress to markdown. Then it comes to syntax highlighting. I used trusty old [highlight.js](https://highlightjs.org) with github theme. Preety strait forward. Then I showed to it some of my colleagues. [Samiul Bhai](https://twitter.com/samhq7) asked me to add disqus as a comment engine. I did that too. Thanks to him. Then I tried to add SSL on the site, but github don't allow SSL in custom domains. So, I integrate cloudflare with the site to enable that. Cloudflare also enables some other great features like DDoS protection, CDN, monitoring etc. After the final result, I am pretty happy what I got now. Please do visit the sections of this site and let me know your thoughts about it. Peace. --- # How to become a Certified Laravel Developer > The steps of becoming a Certified Laravel Developer. Published: 2018-01-09 URL: https://milon.im/post/how-to-become-a-certified-laravel-developer.md I just become a **Certified Laravel Developer** yesterday night. I did attend the exam 4-5 days back. After posting the news in facebook, I was overwhelmed with congratulations and question about the procedure. This blog post is the answer of that question. ![Certified Laravel Developer](/assets/images/posts/laravel-certified-developer.webp) First you need to apply for the certification exam. Unfortunately it's not free and it's not cheap. It's €199 for personal certification. And you you apply for your team with more than 5 developer, you will get 15% discount. More will be found on [certification site](https://laravel.com/certification) including [preparation guideline](https://laravel.com/certification/prepare), and [frequently asked question](http://support.laravelcert.com/support/solutions/folders/30000052876). After registration, you will get a link for the preparation guideline of your workstation. They use [ProctorExam](https://proctorexam.com) as the platform. It's quite an exiting platform, because they ensure the integrity of the exam. They capture your screen while you take the exam, use your webcam to capture your video, use your microphone to record sounds to ensure that you are taking the exam is taken by you, not anyone else. And you have to confirm your identity by uploading one of your photo ID. And as they are recording and uploading all of these to their server, you need to have a good stable internet connection. After sending all these, they will manually check your documents and within 24 hours, you will get the exam link. It's a closed book exam, so using internet or any other secondary device is prohibited. So, don't try to cheat, because they will eventually find out. After get the exam link, you should sit on a well lit room alone. Exam duration is 45 minutes with 45 multiple choice questions. Negative marking is there, so if you are not sure, better leave the question blank. After answering all the questions, you got the chance to review all the question if you got time left. After finishing the exam, they took several days for asses and then you will get the certificate via mail if you pass. They are still working on the certification directory, and it will be published soon. One last thing, exam is not that hard. Try to read the whole laravel documentation quiet a few times, I can guarantee will will pass the exam with ease. Happy coding... --- # Machine Learning Introduction – 1: Set up your workstation > Setting up your workstation for practicing Machine Learning. Published: 2017-02-23 URL: https://milon.im/post/machine-learning-introduction-1-set-up-your-workstation.md Recently, we are planning to use machine learning in one of our core product in Telenor Health. So, I am seriously looking into machine learning for the last few days. Though I have a computer science degree, to be honest, I didn't have a good grasp on machine learning rather than having some basic knowledge of some algorithm like linear regression, K nearest neighbor algorithm and some familiarity with some machine learning term like neural network, deep learning etc. Many people are doing machine learning without having CS degree. So I thought, why not give it a try? ![Machine Learning](/assets/images/posts/machine_learning-1024x724.jpg) I am writing this series in English, though I English is not very good. One reason is this will improve my English writing skill and other thing is my foreign friends could understand what I learn. So, pardon me for my writing. I knew in the field of machine learning, two languages are very popular. One is R and another is Python. As I am already very familiar with Python, so I am going for Python. First you need to install python and other machine learning library. I assume you have already installed python in your machine. Rather than windows every operating system comes with python installed. If not, then do a quick google search and I guarantee you will figure it out. Python has some great library for machine learning. I am going to install them right now. I will be using virtualenv for this cause I don't want my machine filled with these libraries. Python has a very popular distribution called Anaconda. If you are using that, you will have lot of these tools already installed. But I am going for the simpler approach. I will be using pip to install these package. But before that, lets start with virtualenv setup. In your terminal just type- ``` pip install virtualenv ``` Then, I am going to create a new environment called env. ``` virtualenv env -p /usr/local/bin/python3 ``` I will be using python 3.6 throughout this series. So I pass `-p` flag for the python3 path. As I am in macOS, that is my path. You could find the path by writing `which python3` in the terminal. As the environment is created, then you can activate that by typing- ``` source env/bin/activate ``` Make sure whenever you are working with this setup, you always start is form the terminal. If you close the terminal windows, then the environment will be deactivated. You can also deactivate it by typing- ``` deactivate ``` As, our environment is ready, then lets start with numpy. This is a very popular look for numerical calculation in python. ``` pip install numpy ``` Then we will install two other dependencies named pandas and matplotlib. First one is a data analysis tool and second one is for plotting numerical data into beautiful diagram. ``` pip install pandas matplotlib ``` Then lastly install scikit-learn with pip by following command- ``` pip install scikit-learn ``` Though pip should install all the dependencies of scikit-learn, but for some weird reason, it didn't install scipy. So, we have to install it manually as well. ``` pip install scipy ``` Now, as we have setup all our dependencies, we could check it by running- ``` pip freeze ``` You will find a tons of module installed. Thats because the libraries we installed are dependent on those libraries. Our machine is ready for doing some fun with machine learning. See you in next episode. Happy learning. --- # Why you should consider laravel as your go to framework of choice > My thoughts on Laravel framework, and it's usability. Published: 2017-02-04 URL: https://milon.im/post/why-you-should-consider-laravel-as-your-go-to-framework-of-choice.md Recently I was in a debate with 3 other very great software professional at Basis Software Expo, 2017 about Laravel vs Django. I know, comparing between these two is like comparison between orange and apple. Actually, our main target was to present the feature set that these two frameworks offer but in a form of debate so that, people especially the newcomers get a good grasp on these frameworks. We had a very limited time to debate, so we could not focus on all the parts. So, I think why not write a blog post about the topic and thus comes this blog post. Laravel is a very popular web framework, it is the most popular php framework and probably the most popular web framework of any language as well. Though it is comparatively very new, but it has some awesome features. So, here is the features that you should know about laravel- - Laravel has a great community. It is huge and very friendly. - It has arguably the best learning site on the Interner, [Laracasts](https://laracasts.com). [Jeffrey Way](https://twitter.com/jeffrey_way) is a great teacher. - Laravel provides a whole eco-system. It ensures developer's happiness from development to deployment. - Development: Valet, Homedtead - Built in Testing: both unit and browser testing - Code Review: NitpickCI - Asset Management: Elixir, Laravel Mix - Great Task runner: Laravel Envoy - Server Provisioning: Forge - Zero Downtime Deployment: Enroyer - Monitoring Tool: Cachet - Great ORM, built-in Queue System, Out of the box Redis support. - Scaffolding Tools: Spark, Backpack - Stable Release Cycle and LTS support. A new version of laravel comes every 6 months and a long-term support version comes in every 2 years. - Great features, like- realtime broadcasting (Echo), Multiple notification channels, Task schedular, Multiple drivers for most of the components(session, cache, queue, mail, events etc.) - Laravel has some great first party packages - Payment Gateway: Cashier - OAuth2 Server: Passport - Social Authentication: Socialite(support more than 80 sites) - Full-text search: Scout - Laravel is very beginner friendly with very little entry barrier. - Migration, Template Engine with markdown support. - Great Command Line Utility: Artisan. - Tons of community driven packages. To be honest, Laravel is the best thing that happens to me in last 2-3 years. It prevented me from leaving php. I also wrote a bestseller [book](https://milon.im/laravel) on Laravel in Bengali. If you are interested, you can also look into it. --- # লারাভেল ভ্যালে ইনস্টলেশন > কিভাবে লারাভেল ভ্যালে ইনস্টল এবং কনফিগার করবেন আপনার ওয়ার্কস্টেশনে। Published: 2016-05-09 URL: https://milon.im/post/laravel-valet-installation.md গত পরশু(৭ মে, ২০১৬) লারাভেলের নতুন ডেভেলপমেন্ট এনভায়রনমেন্ট লারাভেল ভ্যালে(Valet) রিলিজ দেয়া হয়েছে। এটা ম্যাক অপারেটিং সিস্টেমের জন্য একটা সিম্পলিফায়েড ডেভেলপমেন্ট এনভায়রনমেন্ট। এটা ইনস্টল এবং ব্যবহার করা খুবই সহজ। আপনি শুধুমাত্র আপনার পিসিতে একটি প্রজেক্ট ইনস্টল দিবেন এবং প্রজেক্টের ফোল্ডারের নামের সাথে .dev যুক্ত করে ব্রাউজারে সেটি ব্রাউজ করতে পারবেন। ভ্যালে কি, এটা কিভাবে কাজ করে, এটা নিয়ে এডাম ওয়াদান একটি চমৎকার ভিডিও তৈরি করেছেন। সেটি দেখুন। যারা এর পূর্বে লারাভেলের হোমস্টিড ব্যবহার করতেন, তারা নিশ্চয়ই জানেন সেটা ব্যবহারের জন্য আপনাকে অনেকগুলো ডিপেন্ডেন্সি ইনস্টল করতে হয়। যেমন- ভার্চুয়াল বক্স, ভ্যাগরেন্ট ইত্যাদি। এগুলি ইনস্টল করার পর লারাভেলের হোমস্টিড বক্স ইনস্টল করতে হয়। এই ফাইলগুলি আকারে বেশ বড়, প্রায় কয়েক গিগাবাইট। তাই ইনস্টল করতে প্রচুর সময় লাগে। এরপর প্রত্যেকটা সাইট এড করার সময় হোমস্টিডের yaml ফাইল এডিট করতে হয়। এরপর সেটা প্রভিশনিং করে আপনার মেশিনের hosts ফাইল এডিট করতে হয়। সে তুলনায় ভ্যালে ইনস্টল করা খুবই সহজ এবং এর সাইজও অনেক ছোট। এটা পিএইচপির বিল্ট-ইন সার্ভার ব্যবহার করে, ফলে এটা ব্যবহার করার জন্য আপনাকে এপাচি, এনজিনেক্স বা এ ধরনের ওয়েব সার্ভার ব্যবহার করতে হবে না। শুধুমাত্র পিএইচপি এবং মাইসিক্যুয়েল ইনস্টল করা থাকলেই আপনি ভ্যালে ব্যবহার করতে পারবেন। চলুন দেখি একেবারে নতুন একটি ম্যাক মেশিনে আপনি কিভাবে ভ্যালে ইনস্টল করবেন। প্রথমেই আপনাকে হোমব্রু ইনস্টল করতে হবে। এটা ম্যাকের জন্য একটি প্যাকেজ ম্যানেজার, যার মাধ্যমে আপনি বিভিন্ন ডেভেলপার টুলস খুব সহজেই ইনস্টল করতে পারবেন। আপনি যেহেতু ম্যাক ইউজার, অবশ্যই এটা আপনার মেশিনে ইনস্টল থাকা উচিৎ। এটা ইনস্টল করা খুবই সহজ। আপনি শুধুমাত্র নিচের কমান্ডটি টার্মিনালে চালালেই হবে। ``` /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ``` এরপর এর মাধ্যমে পিএইচপি ইনস্টল করতে হবে। এটা করতে নিচের কমান্ডটি রান করুন- ``` brew tap homebrew/dupes brew tap homebrew/versions brew tap homebrew/homebrew-php brew install php70 ``` যেহেতু আপনি ম্যাক অপারেটিং সিস্টেম ব্যবহার করছেন এটিতে ইতোমধ্যে একটি পিএইচপি ভার্সন ইনস্টল করা থাকে। উপরের কমান্ডের মাধ্যমে আপনি পিএইচপির লেটেস্ট ভার্সন পিএইচপি ৭ ইনস্টল করলাম। এবার কম্পোজার ইনস্টল করবেন নিচের কমান্ডের মাধ্যমে- ``` brew install composer ``` এবারে মাইসিক্যুয়েল ইনস্টল করবেন নিচের কমান্ডের মাধ্যমে- ``` brew install mysql ``` মাইসিক্যুয়েল সার্ভার স্টার্ট করতে নিচের কমান্ডটি দিতে পারেন- ``` brew services mysql start ``` মাইসিক্যুয়েলের যে ইনস্ট্যান্সটি ইনস্টল হয়েছে সেটার ইউজারনেম root এবং পাসওয়ার্ড হিসেবে আছে একটা এম্পটি স্ট্রিং। আপনি টার্মিনাল থেকে নিচের কমান্ডের মাধ্যমে মাইসিক্যুয়েল এক্সেস করতে পারবেন। ``` mysql -uroot ``` এবারে লারাভেল ভ্যালে ইনস্টল করার পালা। এর জন্য টার্মিনালে নিচের কমান্ডটি দিন- ``` composer global require laravel/valet ``` ইনস্টল হয়ে গেলে প্রথমে ভ্যালের বিভিন্ন ডিপেন্ডেন্সি ইনস্টল করুন নিচের কমান্ডের মাধ্যমে- ``` valet install ``` এই কমান্ডটি আপনার মেশিনের সুডো পাসওয়ার্ড চাইবে কারন এটি `dsnmasq` নামে একটি ইউটিলিটি আপনার সিস্টেমে ইনস্টল করবে। এটি করা হয়ে গেলে আপনি যে ফোল্ডারে আপনার প্রজেক্টগুলো রাখতে চান, সেটিতে প্রবেশ করুন। তারপর নিচের কমান্ডটি দিন। ``` cd project-folder valet park ``` ব্যস, আপনার সব কাজ শেষ। ধরুন আমরা এখন একটি নতুন প্রজেক্ট তৈরি করবো ব্লগ নামে। তাহলে প্রথমে এই নামে একটি লারাভেল প্রজেক্ট তৈরি করি। ``` composer create-project laravel/laravel blog --prefer-dist ``` এবার আমরা ব্রাউজারে যদি `blog.dev` ব্রাউজ করি তাহলেই প্রজেক্টটি দেখতে পাবো। শুধু তাই নয়, আপনি যদি এখন এই প্রজেক্টটি আপনার কো-ওয়ার্কারদের সাথে শেয়ার করতে চান সেটিও করতে পারবেন খুব সহজে। আপনি ব্লগ প্রজেক্টের ডিরেক্টরিতে প্রবেশ করুন। তারপর নিচের কমান্ডটি দিন। ``` cd blog valet share ``` এই কমান্ডের মাধ্যমে আপনি একটি ইউআরএল আপনার টার্মিনালে দেখতে পারবেন। এছাড়াও সেটি আপনার ক্লিপবোর্ডে কপি করা অবস্থাতেও পাবেন, শুধুমাত্র পেস্ট করলেই চলবে। কি অসাধারন! ভ্যালে শুধুমাত্র লারাভেলই না আরো অনেক পিএইচপি প্রজেক্টের সাথে আউট অব দ্য বক্স কাজ করে। এছাড়া আপনি চাইলে নিজেও যে কোন প্রজেক্টের জন্য ভ্যালে ড্রাইভার তৈরি করে নিতে পারেন, যা আসলে খুবই সহজ। বিস্তারিত জানতে ভ্যালের [অফিশিয়াল ডকুমেন্টেশন](https://laravel.com/docs/5.2/valet) দেখতে পারেন। আপনি নিশ্চয়ই অবাক হয়েছেন, লারাভেল ভ্যালে কিভাবে এতসব করে? এটার কার্যপদ্ধতি সম্পর্কে বিস্তারিত জানতে [এখানে](http://themsaid.github.io/magic-behind-laravel-valet-20160506/) দেখতে পারেন। --- # Adminer, a great tool for accessing databases > My thoughts on single file RDBMS management tool Adminer. Published: 2016-04-19 URL: https://milon.im/post/adminer-a-great-tool-for-accessing-databases.md Most of the web developers specially who used to write code in PHP, including myself using [phpmyadmin](https://www.phpmyadmin.net/) for a very long time for database management. I myself used this tool for last 6 years or so. But recently I was introduced to a great tool called [adminer](https://www.adminer.org/en/) while facing problem to install phpmyadmin on [homestead](https://laravel.com/docs/5.2/homestead) box. ![Adminer Logo](/assets/images/posts/adminer-logo.png) Long story short, it is a single php file which has almost all the functionality that phpmyadmin has with a bunch of other useful features. Also it supports mySQL, SQLite 2 & 3, PostgreSQL, Oracle, MS SQL, Firebird, SimpleDB, MongoDB and ElasticSearch where phpmyadmin only supports mysql. It is also extremely lightweight and portable as it is only one file. The compressed file is only 231 kB and if you use the English version without 36 other language's translation it turns into 167 kB only. If you use mySQL only, then you reduce the size to 155 kB for translated version and 94 kB for english only version. That's insane. You can find a [full comparison](https://www.adminer.org/en/phpmyadmin) with phpmyadmin to their site. It can work with various plugins and has a bunch of themes. It's released under GPL2 and Apache License and it's totally free to use. Besides that, it has a Debian package, Arch Linux package, WordPress plugin, Drupal module, Joomla extension (1, 2) Moodle plugin, TYPO3 extension, CMS Made Simple Module, Laravel, AMPPS, and Nette package. After finding this, I just uninstall phpmyadmin form my machine and immediately switched to adminer. Hopefully, you would like it also. --- # Never use rm, instead use trash > I thoughts on why everyone should use `trash` command instead of using `rm`. Published: 2016-03-19 URL: https://milon.im/post/never-use-rm-instead-use-trash.md Those who use command line heavily, they use a command called `rm` almost everyday. I myself use command line everyday, and I most often use rm for deleting files and folders. Things getting more worse when you chain `-rf` command with `rm`. Last week I was working on a project and I accidently run `rm -rf` command to my project root directory. Then all my codes were gone and it's not reversible. Thanks to git, I don't loose all my codes, but the latest uncommited changes. After that incident, I tried to find some solution. Then I find an awesome tool called [trash](https://github.com/sindresorhus/trash). It's a simple node module and you can use it to your project. But I installed it globally so that I can use it anywhere on my machine. It deletes your files and folders just like `rm` but it put then to trash. So, you can undo the process. ![Trash Logo](/assets/images/posts/trash.png) The installing process is very strait forward. I assume your machine has already node and npm installed. If not, then install them. After that run this command on your terminal- ``` npm install -g trash-cli ``` If it shows an error, try with `sudo`. Then you are good to go. Using trash is very easy. If you are familiar with `rm` then you are already known to `trash`. It uses similar commands. Here is an example- ``` trash file.txt ``` You can do some complicated operation also. ``` trash '*.png' '!welcome.png' ``` This command will delete all your png files except welcome.png. Hope you will like it, and never use `rm` from now on. Peace. --- # Setting Up Atom Editor for Software Development – 04 > This is the forth part of my setting up development environment in Atom editor by Github. Published: 2016-03-07 URL: https://milon.im/post/atom-editor-for-software-development-04.md Today I am going to talk about a very important topic, and that is Lint. In computer programming, lint is a Unix utility that flags some suspicious and non-portable constructs (likely to be bugs) in C language source code; generically, lint or a linter is any tool that flags suspicious usage in software written in any computer language. According to [wikipedia](https://en.wikipedia.org/wiki/Lint_(software))- > In computer programming, lint is a Unix utility that flags some suspicious and non-portable constructs (likely to be bugs) in C language source code; generically, lint or a linter is any tool that flags suspicious usage in software written in any computer language. Thats bookish knowledge, lets make is a little bit easier to understand. Linter will help to prevent various typo and organize your code in various coding standards. I am a web application developer and I use php and javascript almost everyday. So, in this episode I am going to show you how to use linter in these languages. First of all you have to install the base package for atom linter. It will give you the base functionality and it's a bridge for using specific linter package for various language. You can install linter by typing `apm install linter` or from settings' package installer. This [linter](https://atom.io/packages/linter) package supports a lot of different languages. All the supported packages and ducumentation can be found on I use only some packages that I use for my day to day job. Let me introduce those one by one. At first lets talk about HTML linter. I use [linter-htmlhint](https://atom.io/packages/linter-htmlhint) package for this. This package is just a bridge between atom and famous htmlhint package. You can install it via `apm install linter-htmlhint`. It assume you pc has already htmlhint installed. If not then you could install it through `npm install htmlhint -g` and then give it's path to htmlhint package settings. I assume your machinealre If you don't find the path, then type `which htmlhint` on your terminal and paste the path to the settings. After that I am going to talk about [csslint](https://atom.io/packages/linter-csslint). It's almost the same process, just install it form terminal with `apm install linter-csslint` and configure it same as previous package. You can install [jsonlint](https://atom.io/packages/linter-jsonlint) and [bootlint](https://atom.io/packages/linter-bootlint) for linting json and bootstrap code. Install it by typing `apm install linter-jsonlint` and `apm install linter-bootlint`. Configuring process is exactly the same. ![Linter](/assets/images/posts/linter.png) There are two popular linter for javascript. One is [jshint](http://jshint.com) and other is [jslint](http://www.jslint.com). They are not better from one another, they are just different. I personally use jshint. Install it from terminal by typing `apm install linter-jshint` and then give it's path in settings just like the previous one. I use php a lot and php has some popular linter package. But I think [PHP code sniffer](https://packagist.org/packages/squizlabs/php_codesniffer) is the most popular and one of the best package for php. You can install the package form terminal by typing `apm install linter-phpcs`. It assume youe machine already has phpcs installed. If not you could install it in a number of ways. One of the popular way is to install it through pear. Just type `pear install PHP_CodeSniffer` and you are good to go. But I prefer another way, and it's through composer. If you are a php guy, I assume you have familiarity with both pear and composer. You can install it from terminal with `composer global require "squizlabs/php_codesniffer=*"` command. Then just give the path of phpcs to the settings of the package. Thats it. From now on if you do something wrong while typing, atom linter will show errors. Thats all for today. Peace. --- # Setting Up Atom Editor for Software Development – 03 > This is the third part of my setting up development environment in Atom editor by Github. Published: 2016-03-06 URL: https://milon.im/post/atom-editor-for-software-development-03.md In this episode I am going to talk about some basic package of atom. I told you earlier that atom is a text editor and it is not as feature rich as other IDEs like PhpStorm or Netbeans. But you could give it additional functionality with various packages. First I am talking about a package that will give a nice look to your editor. The package is called [file-icons](https://atom.io/packages/file-icons). A number of icons and colors are provided by default for a range of common file types. If you have file that you would like custom icons for you can easily add this yourself. You can install it with this command- `apm install file-icons` or from settings menu's install tab. ![File Icons](/assets/images/posts/file-icon.png) The next package is inspired by Sublime Text's minimap feature. Actually I am a very big fan of [minimap](https://atom.io/packages/minimap) and I use this feature in every editor I use. Install it through `apm install minimap` or via settings menu. From settings menu you can change the position either in left or right and enable or disable colors. You can also scroll via clicking on minimap and also automatic hide minimap pane. ![Minimap](/assets/images/posts/minimap.png) Now I am talking about a very famous package that you might already familiar with. It is none other emmet, which was used to known as zen coding. It will boost up your development speed a lot. You can find the documentation and installation instruction on their official website [emmet.io](http://emmet.io) What emmet does is with a keypress it expand HTML tags. like if you type `a>img` and then press `tab` or `Ctrl+e` then it will expand to `` which is very handy. But for atoms default keybinding, tab is not working all the time. You could add the following line to you `config.cson` file to work it properly. ``` # Emmet 'atom-text-editor:not([mini])': 'tab': 'emmet:expand-abbreviation-with-tab' ``` I generally use markdown instead any rich text editor like MS Word or Libre Office. If you are like me [Markdown preview plus](https://atom.io/packages/markdown-preview-plus) can be a great tool for you. Just install the package from package installer and press `ctrl+shift+m` to view preview. For mathematical equation rendering press `Ctrl+shift+x` and see the magic. Thats all for today. See you guys in the next episode. Piece. --- # Setting Up Atom Editor for Software Development – 02 > This is the second part of my setting up development environment in Atom editor by Github. Published: 2016-03-03 URL: https://milon.im/post/atom-editor-for-software-development-02.md Let's start configuring atom's look and feel. Atom comes with two types of visual themes. One type is UI theme and other is Syntax theme. UI theme defines the look and feel of the editor and syntax theme defines the syntax highlighting. Atom comes with a bunch of UI themes, actually four to be precise. The default one is One Dark. I like it most. Actually I like this theme so much that I used it with my other editors even with my terminal. There are some more popular themes for atom especially material theme is very popular. You can find any themes on [atom's official theme portal](https://atom.io/themes). Now lets talk about syntax theme. There are mainly two types of syntax theme, the light one and the dark one. I personally a very big fan of dark themes, I think most of the developer is. Currently I am using One Dark syntax theme. I actually change syntax more very often. Seti syntax is probably the most popular theme of atom. Material theme is also popular. I used them both. You can find tons of other theme on atom's theme directory. I liked a syntax theme named Space Peacock very much, you can give a try with that too. I hope you would love that. ![One Dark Theme](/assets/images/posts/one-dark.png) [Solarized](http://ethanschoonover.com/solarized) is also a very popular theme for any editor or IDE and it is very pleasant to eyes. In facts most of the popular themes are available for every editor or IDE. Installation of theme is very strait forward. You can install them via settings menu. You can go to settings menu by pressing `Cmd + ,` on mac or `Ctrl + ,` on windows or linux. Go install tab and search your desired theme and then press install. You are good to go. Then form the settings menu you just change the theme. ![Install Packages](/assets/images/posts/install-packages.png) ![apm](/assets/images/posts/apm.png) Atom also comes with a command line package manager called `apm`. After installing atom you can go your terminal and type `apm -v` to verify. You can install theme via `apm` also. I actually prefer using amp. You can install theme via `apm` also. Just type `apm install theme-name` and press install. Theme will be installed. That's all for today, will talk to you on the next day. Peace. --- # Setting Up Atom Editor for Software Development – 01 > This is the first part of my setting up development environment in Atom editor by Github. Published: 2016-03-02 URL: https://milon.im/post/atom-editor-for-software-development-01.md People who are dealing with writing code for full time job, actually passes 40 hours of more on a week to their text editor or IDE. I am a software developer by profession and I normally code 45-50 hours per week that means I had to stick with my text editor for most of time. So, my text editor should be something that I should comfortable with. In this series of blog posts I will tell you how I prepare my text editor for my work. Let's start. ![Atom Editor](/assets/images/posts/atom-editor.png) Let's begin with some history. I would love to tell you about this. I started computer programming back in 2009 with C. In my university my teachers used a compiler called turbo c with comes with a text editor. I started my coding with that. Then a few days later I got introduced with CodeBlocks. It is a wonderful editor, and I still love that. I do almost all my competitive programming with this editor. Then at the end of second semester, I started writing code in Java. That time my roommate Sohag Bhai introduced me with jEdit. This had some nifty keyboard shortcuts to compile and run Java. Then when I do my university project in Java, I used a very famous IDE called Netbeans. Besides that for other programming language like assembly, prolog, lisp and matlab code I used notepad++ on windows and an open source text editor called geany in linux. Actually I liked notepad++ more than any other text editor but it was available on linux on that time. I don't know whether it is available on other platform right now, hope it is as we can run C# code other platform. After that I started using php and I still used Netbeans for php. But Netbeans is a very heavy-weight IDE and it almost killed my 2GB RAM. So I want something fast and light-weight. Then I started using the great Sublime Text. After finishing my university I joined in job and there my colleague Prasit Dada introduced me with PhpStorm. It is a great IDE and I used it with almost two years. This is the first IDE that I paid money for. But recently I was little unhappy with their new pricing model. I still have the license for PhpStorm but I don't use this that much. I the mean time, I tried various different text editors like adobe's brackets, github's atom and a bunch of other tools, but all them failed to win my preference. Last year I visited a startup company called [Backpack](https://backpackbang.com) which you may familiar with and I saw one my coding idol [Rifat Bhai](https://twitter.com/rifat) using atom. Last time when I used atom, performance was not very pleasant. I talk to him about it, and he inform me atom's 1.0 version was released a couple of days back and I got a huge feature and performance boost. That day after coming back to my home, I gave a shot to atom and I was surprised. From that day I am using atom as my primary text editor. One thing I forgot to mention, I used Vim for a long time as my secondary editor. Vim has a huge learning curve and I am still a noob on Vim. I don't remember when did I first used Vim, but I thing it is [Ring Bhai](https://twitter.com/toshazed) who introduced me with Vim when I first started using linux OS. Now lets talk something about [atom](https://github.com/atom). Atom is an open source project by Github and it is based on electron shell. Github uses html, css and coffee script to build atom. It is available on every platform and every parts and bits are configurable. It is not as fast as Sublime Text right now but with every release it gains performance boost, but it is good enough for me. In this series I will show you how I configure atom for myself. Starts with installing atom. Atom installer can be downloaded from their [official website](https://atom.io) and steps are very easy and strait forward. Just download the installer and install it. As you are reading this, I assume you can do this without any supervision. That's all for today, will talk to you on next episode. Peace. --- # লারাভেলে একাধিক রাউটিং ফাইলের ব্যবহার > লারাভেলে একাধিক রাউটিং ফাইল ব্যবহার বিধি। (আপডেট: লারাভেল ৫.৫ এ এই ফিচারটি যুক্ত করা হয়েছে।) Published: 2016-02-16 URL: https://milon.im/post/laravel-multiple-route-files.md > আপডেট: লারাভেল ৫.৫-এ এই ফিচারটি যুক্ত করা হয়েছে। লারাভেলে চমৎকার একটি রাউটিং লাইব্রেরি সহ এসেছে, যা সিম্ফনির রাউটারের উপর ভিত্তি করে তৈরি করা। আর এটি ব্যবহার করাও খুব সহজ। এর চমৎকার এপিআই সেল্ফ এক্সপ্লেনারি। যে কেউ রাউটারের কোড দেখলেই বুঝতে পারবে, এটি কি কাজ করবে। চলুন একটু উদাহরন দেখি- ```php group(['namespace' => $this->webNamespace], function ($router) { require app_path('Http/web_routes.php'); }); $router->group(['namespace' => $this->apiNamespace], function ($router) { require app_path('Http/api_routes.php'); }); } } ``` এরপর থেকে আপনি আপনার ওয়েবসাইটের রাউটগুলি ওয়েব রাউট ফাইলে এবং এপিআই রাউটগুলি এপিআই রাউট ফাইলে আলাদা করে রাখতে পারবেন। আপনি আপনার প্রয়োজনমত যতগুলি ইচ্ছা ফাইলে রাউটগুলি ভাগ করে রাখতে পারেন। আর রাউট ফাইলের সংখ্যা যদি বেড়ে যায়, তাহলে সেগুলিকে `Http` ফোল্ডারের মধ্যে `Routes` নামে একটি ফোল্ডারে রাখতে পারেন। সেক্ষেত্রে ম্যাপ মেথডে শুধু রাউট ফাইলের পাথটি ঠিক করে দিলেই হবে। --- # লারাভেল হোমস্টিড ইনস্টলেশন > লারাভেল হোমস্টিডের মাধ্যমে ডেভেলপমেন্ট এনভায়রনমেন্ট তৈরি করা। Published: 2016-02-10 URL: https://milon.im/post/laravel-homestead-installation.md লারাভেল একটি চমৎকার পিএইচপি ফ্রেমওয়ার্ক। যারা লারাভেল শিখতে চায় তারা প্রথমেই যে সমস্যাটার কথা বলেন, সেটি হচ্ছে এর ডেভেলপমেন্ট এনভায়রনমেন্ট সেটআপ করা। লারাভেলের অনেকগুলি ডিপেন্ডেন্সি আছে। যেমন লারাভেল ৫.২ এর সার্ভার রিকোয়ারমেন্ট হচ্ছে- - PHP >= 5.5.9 - OpenSSL PHP Extension - PDO PHP Extension - Mbstring PHP Extension - Tokenizer PHP Extension এছাড়া পুরনো ভার্সনের লারাভেলে পিএইচপির `mcrypt` এক্সটেনশন ব্যবহার করা হতো। এগুলি সেটআপ করা ঝামেলার এবং সময়সাপেক্ষ। এছাড়াও ওয়েব সার্ভার যেমন- এনজিনেক্স, ডেটাবেজ সার্ভার, রেডিস সার্ভার, মেমক্যাশ সার্ভার, কিউ সার্ভার যেমন- বিনস্টকড ইনস্টল এবং কনফিগার করা অত্যন্ত ঝামেলার। এছাড়া কিছু টুল যেমন- বিনস্টকড উইন্ডোজ মেশিনে ইনস্টলও করা যায় না। লারাভেল এ ঝামেলা থেকে বাঁচানোর জন্য খুব সহজ একটি উপায় তৈরি করে রেখেছে। এটি হচ্ছে লারাভেলের ডেভেলপমেন্ট এনভায়রনমেন্ট যা হোমস্টিড নামে পরিচিত। ![Laravel loves Vagrant](/assets/images/posts/laravel-vagrant.png) হোমস্টিড ভ্যাগরেন্ট নামে একটি সার্ভিস ব্যবহার করে তৈরি করা হয়েছে, যা আসলে ভার্চুয়াল মেশিনের একটি এবস্ট্রাকশন। ভার্চুয়াল মেশিন কি আমরা সবাই জানি। এটি হচ্ছে আপনার মেশিনের বা অপারেটিং সিস্টেমের ভেতরে চলমান আরেকটি মেশিন বা অপারেটিং সিস্টেম। বর্তমানে প্রচলিত সবচেয়ে জনপ্রিয় দুটি ভার্চুয়াল মেশিন সফটয়্যারের নাম হচ্ছে ভার্চুয়াল বক্স এবং ভিএমওয়্যার। হোমস্টিড এ দুটি প্রোভাইডারই সাপোর্ট করে, তবে এটির ডিফল্ট প্রোভাইডার হলো ভার্চুয়াল বক্স। এ উদাহরনেও আমরা ভার্চুয়াল বক্সই ব্যবহার করবো। এর প্রধান কারন হচ্ছে ভিএমওয়্যারের ভ্যাগরেন্ট প্রোভাইডার কিনতে হয় যেখানে ভার্চুয়াল বক্সেরটা ফ্রি। ভার্চুয়াল মেশিন সম্পর্কে আরো বিস্তারিত জানতে [এখানে](https://en.wikipedia.org/wiki/Virtual_machine) ঢু মারতে পারেন। অনেক কথা হলো, এবার চলুন কিভাবে আপনি আপনার পিসিতে হোমস্টিড সেটআপ করবেন তা দেখি। প্রথম ধাপ হচ্ছে ভার্চুয়াল বক্স ডাউনলোড করে ইনস্টল দেয়া। এটি খুবই সহজ। আপনি ভার্চুয়াল বক্সের [অফিশিয়াল ওয়েবসাইট](https://www.virtualbox.org/wiki/Downloads) থেকে অপারেটিং সিস্টেমের জন্য প্রয়োজনীয় ইনস্টলারটি ডাউনলোড করে ইনস্টল করে নিবেন। এরপর ভ্যাগরেন্টের [অফিশিয়াল সাইট](https://www.vagrantup.com/downloads.html) থেকে ইনস্টলার ডাউনলোড করে সেটিও ইনস্টল করে নেবেন। লক্ষ্য রাখবেন, এ দুটি সফটয়্যারের ইনস্টল লোকেশন যেন আপনার পাথ ভ্যারিয়েবলে থাকে। বাই ডিফল্ট এটি আপনার পাথেই ইনস্টল হবার কথা, তাই এ নিয়ে চিন্তা না করলেও চলবে। এ অবস্থায় আপনি যদি আপনার টার্মিনালে নিচের কমান্ডটি লিখেন, তাহলে দেখবেন- ``` vagrant -v 1.8.1 ``` এবার আপনি নিচের কমান্ডটির মাধ্যমে হোমস্টিড বক্স এড করুন আপনার মেশিনে- ``` vagrant box add laravel/homestead ``` এই কমান্ডটি বেশ খানিকটা সময় নেবে, কারন এর মাধ্যমে প্রায় ১ গিগাবাইট ডেটা ডাউনলোড হবে, যার মধ্যে উবুন্টু, সমস্ত সার্ভার, ডেটাবেজ, কনফিগারেশন ফাইল থাকবে। এবার আপনি আপনার রুট ডিরেক্টরিতে যান, এবং নিচের গিট কমান্ডটির মাধ্যমে হোমস্টিডের গিট রিপোজিটরিটি ক্লোন করুন। আপনার মেশিনে যদি গিট ইনস্টল করা না থাকে, এখনই করে নিন। ``` cd ~ git clone https://github.com/laravel/homestead.git Homestead ``` এরপর আপনি হোমস্টিড ডিরেক্টরিতে প্রবেশ করুন, নিচের কমান্ডটি দিন- ``` cd ~/Homestead bash init.sh ``` এই কমান্ডটির ফলে আপনার রুট ডিরেক্টরিতে `.homestead/Homestead.yaml` নামে একটি ফাইল তৈরি হবে। এই ফাইলটি আপনার হোমস্টিডের কনফিগারেশন ফাইল। এটি দেখতে অনেকটা এরকম- ``` ip: "192.168.10.10" memory: 2048 cpus: 1 provider: virtualbox authorize: ~/.ssh/id_rsa.pub keys: - ~/.ssh/id_rsa folders: - map: ~/Code to: /home/vagrant/Code sites: - map: homestead.app to: /home/vagrant/Code/homestead/public databases: - homestead # blackfire: # - id: foo # token: bar # client-id: foo # client-token: bar # ports: # - send: 50000 # to: 5000 # - send: 7777 # to: 777 # protocol: udp ``` এই ফাইলের প্রথমেই আছে আইপি, মেমরি, সিপিইউ এবং প্রোভাইডার। আইপি হচ্ছে যে আইপি থেকে আপনি আপনার ভ্যাগরেন্ট বক্স এক্সেস করতে পারবেন, মেমরি হচ্ছে ভ্যাগরেন্ট বক্সে আপনি কি পরিমান মেমরি এলোকেট করতে চান, সিপিইউ হচ্ছে ভ্যাগরেন্ট বক্সের সিপিইউ কোরের সংখ্যা। এরপরের অথোরাইজ এবং কি হচ্ছে আপনার এসএসএইচ কি যার মাধ্যমে আপনি ভ্যাগরেন্ট বক্সে ঢুকতে পারবেন। আপনার যদি গিটহাবে কোন একাউন্ট থেকে থাকে তাহলে আপনি খুব সহজেই আপনার পিসিতে এসএসএইচ কি তৈরি করে নিতে পারেন। এটি সম্পর্কে বিস্তারিত জানতে [এখানে](https://help.github.com/articles/generating-an-ssh-key) দেখুন। এরপরই আছে ফোল্ডার অপশন। এর প্রথমে আছে map কি, যা আপনার পিসির একটি ফোল্ডারকে নির্দেশ করবে, আর to কি আপনার ভ্যাগরেন্ট বক্সের একটি ফোল্ডারকে নির্দেশ করবে। এই দুইটি ফোল্ডার একটি অপরটির সাথে সিনক্রোনাইজেশনে থাকবে। যার ফলে আপনি আপনার লোকাল মেশিনে ফাইল চেঞ্জ করলে আপনার ভার্চুয়াল বক্সেও ফাইলটি চেঞ্জ হয়ে যাবে। আমরা এক্ষেত্রে ডিফল্ট সেটিংসই ব্যবহার করবো। এরপর আমাদের পিসির রুটে Code নামে একটি ফোল্ডার তৈরি করলেই চলবে। এরপরই আছে sites অপশন, যেটা আপনার প্রজেক্টকে নির্দেশ করবে। এর ম্যাপ কি আপনার কাস্টম ডোমেইন, এবং টু কি আপনার প্রজেক্টের পাবলিক পাথ নির্দেশ করবে। বাই ডিফল্ট homestead.app নামে একটি ডোমেইন ম্যাপ করা থাকে। এরপর আছে ডেটাবেজেস কি, যেটিতে উল্লেখ করা প্রত্যেকটি কি-এর নামে একটি করে ডেটাবেজ তৈরি অটোমেটিক্যালি তৈরি হবে। এর নিচে আছে ব্ল্যাকফায়ার এবং পোর্টস কি, যা ডিফল্টভাবে কমেন্ট আউট করা থাকবে। আপনি যদি ব্ল্যাকফায়ার প্রোফাইলার ব্যবহার করেন তাহলে সেটি আনকমেন্ট করবেন এবং যদি ডিফল্ট পোর্ট ওভাররাই করতে চান তাহলে পোর্টস কি আনকমেন্ট করবেন। আমাদের ভ্যাগরেন্ট সেটআপের কাজ শেষ। এবার চলুন ভ্যাগরান্ট চালু করে দেখি। এর জন্য যে ফোল্ডারে আমরা হোমস্টিডের গিট রিপোজিটরি ক্লোন করেছি সেটিতে ঢুকতে হবে। তারপর নিচের কমান্ডটি দিতে হবে- ``` cd ~/Homestead vagrant up ``` এই কমান্ডের মাধ্যমে আপনার ভ্যাগরেন্ট সার্ভার চালু হবে। এবার ভ্যাগরেন্ট মেশিনে লগ-ইন করতে নিচের কমান্ডটি লিখুন- ``` vagrant ssh ``` এবার আপনি আপনার ভ্যাগরেন্ট মেশিনে আপনার অ্যাপ্লিকেশন ডেভেলপমেন্ট চালিয়ে যেতে পারবেন। চলুন, প্রথমেই আমরা নিচের কমান্ডটির মাধ্যমে লারাভেল ইনস্টল দিই- ``` composer create-project laravel/laravel homestead --prefer-dist ``` এবার আপনার এই টার্মিনাল চালু থাকা অবস্থায় আরেকটি টার্মিনাল উইন্ডোতে আপনার হোস্ট ফাইলটি ওপেন করুন। লিনাক্স বা ম্যাক অপারেটিং সিস্টেমে এটি থাকে `/etc/hosts` নামক ফাইলে। সেটিতে নিচের লাইনটি যুক্ত করুন- ``` 192.168.10.10 homestead.app ``` এবার আপনার ব্রাউজারে `homestead.app` ইউআরএলে ঢুকলে আপনি লারাভেলের ডিফল্ট ওয়েলকাম পেজটি দেখতে পাবেন। যদি কখনো আপনার আরো কোন প্রজেক্ট যুক্ত করার প্রয়োজন পড়ে, তাহলে আপনি `.homestead/Homestead.yaml` ফাইলে এডিট করে সাইটস সেকশনে আরেকটি কি-ভ্যালু পেয়ার যুক্ত করুন এবং আপনার হোস্ট ফাইলে ম্যাপিং ইউআরএলটি একই আইপিতে ম্যাপ করুন। এবার আপনার ক্লোন করা হোমস্টিড ফোল্ডারে ঢুকে নিচের কমান্ডটি দিন- ``` vagrant provision ``` আশা করি আপনার হোমস্টিড সেটআপ করতে কোন সমস্যা হবে না। যদি এরপরও কোন সমস্যায় পড়েন তাহলে [লারাভেলের ডকুমেন্টেশনে](https://laravel.com/docs/5.2/homestead) দেখতে পারেন অথবা নিচের কমেন্টে আমাকে জানাতে পারেন। --- # উবুন্টুতে রেডিস ইনস্টল > উবুন্টু অপারেটিং সিস্টেমে রেডিস ইনস্টলেশন গাইডলাইন। Published: 2015-07-06 URL: https://milon.im/post/install-redis-in-ubuntu.md রেডিস একটি চমৎকার ইন-মেমরি, ওপেন সোর্স কি-ভ্যালু স্টোর। রেডিসকে আপনি বিভিন্ন কাজে ব্যবহার করতে পারেন। আপনার ক্যাশ ড্রাইভার, সেশন ড্রাইভার হিসেবে যেমন ব্যবহার করতে পারেন, তেমনি ডেটা স্টোরেজ হিসেবেও ব্যবহার করতে পারেন। রেডিস অনেকটা মেমক্যাশের মত, মানে এটি ইন-মেমরি ডেটা স্টোরেজ, ফলে এটি অত্যন্ত ফাস্ট কাজ করতে পারে, তবে এতে বিল্ট ইন পারসিসটেন্স ম্যাকানিজম আছে। ফলে মেমক্যাশের মত সার্ভার রিস্টার্ট দিলে ডেটা হারিয়ে যায় না। ![Redis](/assets/images/posts/redis.png) রেডিসের আছে ৭ ধরনের ডেটা স্টোর করার সুবিধা। এগুলো হচ্ছে, স্ট্রিং, সেট, সর্টেড সেট, লিস্ট, হ্যাশ, বিটম্যাপ এবং হাইপারলগলগ। এর আছে অত্যন্ত চমৎকার ডকুমেন্টেশন এবং বিশাল হেল্পফুল কমিউনিটি। আপনি প্রায় সব প্রোগ্রামিং ভাষার জন্য রেডিসের ড্রাইভার পাবেন। ফলে আপনার যদি বিভিন্ন প্রোগ্রামিং ভাষার মধ্যে ডেটা আদান-প্রদানের প্রয়োজন পড়ে, সেক্ষেত্রে রেডিস হতে পারে চমৎকার একটি সল্যুশন। এছাড়াও রেডিসের রয়েছে বিল্টইন পাব-সাব ম্যাকানিজম। ধরুন, মাইসিক্যুয়েলে আপনি এইমাত্র একটি কোয়েরি করে একটা টেবিল থেকে ডেটা নিয়ে এসেছেন। আপনি কোয়েরি করার পর পরই সে টেবিলে অন্য কেই নতুন একটি রো ইনসার্ট করলো। সেক্ষেত্রে আরেকটি কোয়েরি করার আগ পর্যন্ত আপনি সেই নতুন রো টি সম্পর্কে জানতে পারবেন। কিন্তু আপনি যদি রেডিস ব্যবহার করে থাকেন এবং সেই কি-তে সাবস্ক্রাইব করে রাখেন, তবে আপনি একটা নতুন ডেটা ইনসার্ট হওয়ার সাথে সাথেই পেয়েই যাবেন। এবার চলুন দেখি রেডিস কিভাবে ইনস্টল করবেন। প্রথমেই বলে নেই, আমি উইন্ডোজ ব্যবহার করি না অনেকদিন হলো। তাই উইন্ডোজে এটা কিভাবে ইনস্টল করবেন সে ব্যাপারে ধারনা দিতে পারছি না। তবে আপনি গুগল সার্চ করলেই পেয়ে যাবেন। আমি আপনাদেরকে দেখাবে লিনাক্সে কিভাবে রেডিস ইনস্টল করবেন। আমি উবুন্টু ব্যবহার করছি। আপনি অন্য যে কোন লিনাক্স ডিস্ট্রিবিউশনে বা ম্যাক অপারেটিং সিস্টেমেও একই কমান্ডের মাধ্যমে রেডিস ইনস্টল করতে পারবেন। প্রথমেই রেডিস কম্পাইল করার জন্য আপনার পিসিতে কিছু ডিপেন্ডেন্সি লাগবে। সেগুলি ইনস্টল করতে পারবেন নিচের কমান্ডের মাধ্যমে- ``` sudo apt-get install build-essential sudo apt-get install tcl8.5 ``` এরপর আমরা রেডিসের [অফিশিয়াল সাইট](http://redis.io) থেকে রেডিসের লেটেস্ট ভার্সনের সোর্স কোড ডাউনলোড করবো। আপনি চাইলে নিচের কমান্ডের সাহায্যেও ডাউনলোড করতে পারেন- ``` wget http://download.redis.io/releases/redis-3.0.2.tar.gz ``` এবার ডাউনলোড করা ফাইলটি আনটার করে নিন- ``` tar xzf redis-3.0.2.tar.gz ``` এবার রেডিসকে কম্পাইল এবং ইনস্টল করার জন্য নিচের কমান্ডগুলো দিন- ``` make make test sudo make install ``` রেডিসকে যদি আপনার সিস্টেমে গ্লোবালি ইনস্টল করতে চান তাহলে টার্মিনালে নিচের কমান্ড দুইটি লিখুন- ``` cd utils sudo ./install_server.sh ``` আপনি যদি রেডিসকে একটি সার্ভিস হিসেবে ইনস্টল করতে চান, অর্থাৎ আপনার পিসি স্টার্ট হবার সাথে সাথেই রেডিস সার্ভারকে চালু করতে চান তাহলে নিচের কমান্ডটি টার্মিনালে লিখুন- ``` sudo update-rc.d redis_6379 defaults ``` ব্যাস, আপনার পিসিতে রেডিস ইনস্টল করা হয়ে গেছে। টেস্ট করার জন্য টার্মিনালে লিখুন- ``` redis-cli ``` আপনি আউটপুট হিসেবে রেডিস কনসোল দেখতে পারবেন- ``` 127.0.0.1:6379> ``` তো শুরু করে দিন রেডিস ব্যবহার করা। হ্যাপি কোডিং... --- # লারাভেল ৫.১-এ কাস্টম পেজিনেশন > লারাভেল ৫.১ ব্যবহার করে কাস্টম পেজিনেটেড কোয়েরি লেখার গাইডলাইন। Published: 2015-07-05 URL: https://milon.im/post/laravel-custom-pagination.md লারাভেলের ইলোকোয়েন্ট বা কোয়েরি বিল্ডার ব্যবহার করে আপনি খুব সহজেই পেজিনেশন তৈরি করতে পারেন। নিচে উদাহরন দেখুন- ```php public function show() { $people = People::paginate(5); return view('poeple.list', compact('people')); } ``` আর পেজিনেশন লিঙ্কগুলো ভিউ পেজে শো করতে হয় এভাবে- ```blade {!! $people->render() !!} ``` কিন্তু আমরা সবসময় ইলোকোয়েন্ট বা কোয়েরি বিল্ডার ব্যবহার নাও করতে পারি। সেক্ষেত্রে পেজিনেশনের দরকার হলে সেটি করতে হবে এভাবে- ```php public function index() { $people = collect([ [ 'name' => 'Milon', 'website' => 'http://milon.im' ], [ 'name' => 'Sadek', 'website' => 'http://sadek.im' ], //many other items... [ 'name' => 'Ashik', 'website' => 'http://ashik.im' ] ]); $perPage = 5; $currentPage = \Input::get('page') ?: 1; $pagedData = $people->slice($currentPage * $perPage, $perPage)->all(); $people = new \Illuminate\Pagination\LengthAwarePaginator($pagedData, count($people), $perPage, $currentPage); return view('people.list', compact('people')); } ``` এখানে প্রথমে একটা বড় এ্যারে কে ‌‌collect() হেল্পার মেথডের সাহায্যে লারাভেলের কালেকশন ক্লাসের অবজেক্টে পরিনত করা হয়েছে। এরপর $perPage এ ঠিক করা হয়েছে প্রতি পেজে কয়টা ডেটা শো করবে। এরপর কারেন্ট পেজ কোনটা সেটা নির্ধারন করা হয়েছে ইউআরএলের GET প্যারামিটার থেকে। যদি কোন গেট প্যারামিটার না থাকে তবে আমরা ডিফল্টভাবে $currentPage = 1 ধরে নেই। এরপর ডেটাকে স্লাইস করে নিতে হয়। এই স্লাইস মেথড কিভাবে কাজ করে সেটা লারাভেলের [কালেকশনের ডকুমেন্টেশন](http://laravel.com/docs/5.1/collections#method-slice) দেখে নিতে পারেন। পরবর্তীতে এই ডেটাকে LengthAwarePaginator ক্লাসের ইন্সট্যান্স বানাতে হয়। LengthAwarePaginator ব্যবহার না করে আপনি চাইলে Paginator ক্লাসও ব্যবহার করতে পারেন। এ দুটির মধ্যে পার্থক্য হচ্ছে LengthAwarePaginator ক্লাসটিতে আপনার কালেকশনে মোট কয়টি ডেটা আছে সেটা পাঠাতে হয় কিন্তু Paginator এ সেটা পাঠাতে হয় না। বাকি ভিউ আপনি নিচের মত করে রেন্ডার করতে পারেন- ```blade
@foreach($collection as $data) @endforeach
Name Website
{{ $data['name'] }} {{ $data['website'] }}
{!! $collection->render() !!}
``` হ্যাপি কোডিং... --- # লারাভেল ব্লেডের সাথে অ্যাঙ্গুলার বা অন্যান্য জাভাস্ক্রিপ্ট টেমপ্লেটিংয়ের ব্যবহার > লারাভেল ব্লেড টেমপ্লেটের সাথে অ্যাঙ্গুলার বা মাসট্যাশের মত জাভাস্ক্রিপ্ট টেমপ্লেটিং লাইব্রেরি একত্রে ব্যবহার করার কৌশল। Published: 2015-06-19 URL: https://milon.im/post/using-blade-with-js-templating.md ![Laravel loves Angular](/assets/images/posts/angular-laravel.jpg) আপনারা ইতোমধ্যে জানেন লারাভেলের টেমপ্লেটিং ইঞ্জিনের নাম ব্লেড আর এতে যে কোন ভ্যালু প্রিন্ট করার জন্য ডাবল কার্লি ব্রাকেট ব্যবহার করা হয়। যেমন- ```blade Total Student: {{ $totalStudent }} ``` এখন অনেক জাভাস্ক্রিপ্ট লাইব্রেরি এবং টেমপ্লেটিং ইঞ্চিনও এই একই সিনট্যাক্স ব্যবহার করে। যেমন- অ্যাঙ্গুলারজেএস, ভিউজেএসের মত জাভাস্ক্রিপ্ট লাইব্রেরি বা মাসট্যাশ(mustache) বা হ্যান্ডেলবারের মত টেমপ্লেটিং লাইব্রেরি। সেক্ষেত্রে আপনি লারাভেলের ব্লেড আর জাভাস্ক্রিপ্ট টেমপ্লেটিং ইঞ্জিনের মধ্যে কলিশন হয় এবং আপনার কোড ঠিকমত কাজ করে না। এ সমস্যা থেকে সমাধানের দুইটি উপায় রয়েছে। প্রথমটি হচ্ছে জাভাস্ক্রিপ্ট টেমপ্লিটিং এবং ব্লেডের মধ্য থেকে যে কোন একটির সিনট্যাক্স পরিবর্তন করে নেয়া। এক্ষেত্রে প্রথমেই চলুন দেখি কিভাবে আপনি ব্লেডের সিনট্যাক্স পরিবর্তন করবেন। আপনি আপনার রাউট ফাইলের শুরুতেই লিখতে পারেন- ```php //For changing content tag Blade::setContentTags('<%', '%>'); //For changing escaped content Blade::setEscapedContentTags('<%%', '%%>'); ``` এই কোডের জন্য এখন থেকে কনটেন্ট ট্যাগের সিনট্যাক্স পরিবর্তিত হয়ে গেল। আপনি চাইলে আপনার পছন্দমত সিনট্যাক্স ব্যবহার করতে পারেন। আর আপনি যদি এই কোডটুকু রাউট ফাইলে না রেখে আরেকটু গুছিয়ে রাখতে চান, সেটিও করতে পারবেন এটিকে একটি একটি সার্ভিস প্রোভাইডারের মধ্যে রেখে। আমি নিজে অবশ্য সেটিকেই বেশি পছন্দ করবো। আপনি চাইলে জাভাস্ক্রিপ্ট ইঞ্জিনের সিনট্যাক্সও পরিবর্তন করতে পারবেন। এখন একেক জাভাস্ক্রিপ্ট লাইব্রেরির সিনট্যাক্স যেহেতু একেক রকম, এক্ষেত্রে আমরা অ্যাঙ্গুলারের উদাহরন দেখি যেহেতু এটি সবচেয়ে বেশি ব্যবহৃত। ```javascript var sampleApp = angular.module('sampleApp', [], function($interpolateProvider) { $interpolateProvider.startSymbol('<%'); $interpolateProvider.endSymbol('%>'); }); ``` এবার চলুন দেখি দ্বিতীয় পদ্ধতি। এটা সবচেয়ে সহজ এবং এর জন্য আপনাকে কোন কনফিগারেশনও ঠিক করতে হবে না। যে ভ্যালুগুলো আপনি চান ব্লেড এক্সেপ করে যাক, আপনি সেগুলির শুরুতে শুধুমাত্র একটি @ সিম্বল বসিয়ে দিন। যেমন- ```blade Total Student: @{{ $totalStudent }} ``` ব্যস হয়ে গেল। তো শুরু করে দিন লারাভেলের সাথে জাভাস্ক্রিপ্ট টেমপ্লেটিং। হ্যাপি কোডিং... --- # উবুন্টু ১৪.০৪ ভার্সনে পিএইচপি ৫.৬ ইনস্টল করা > উবুন্টু ১৪.০৪ এ পিএইচপি ভার্সন ৫.৬ ইনস্টল এবং কনফিগার করার পদ্ধতি Published: 2015-06-14 URL: https://milon.im/post/install-php-5-6-in-ubuntu.md ![Ubuntu loves PHP](/assets/images/posts/ubuntu-php.jpg) উবুন্টুর সর্বশেষ এলটিএস রিলিজ হচ্ছে উবুন্টু ১৪.০৪। কিন্তু এর অফিশিয়াল রিপোজিটরিতে পিএইচপি ৫.৫.৯ ভার্সন দেয়া আছে। আপনি যদি উবুন্টুতে পিএইচপি ৫.৬ ভার্সন ইনস্টল করতে চান তাহলে সেটা অফিশিয়াল রিপোজিটরি থেকে করতে পারবেন না। চিন্তার কিছু নেই। আপনি খুব সহজেই [আদ্রেজ সুরি](https://launchpad.net/~ondrej/+archive/ubuntu/php5-5.6)র তৈরি করা পিপিএ যোগ করে, একটা কমান্ডের মাধ্যমেই পিএইচপি ৫.৬ ইনস্টল দিতে পারবেন। এর জন্য প্রথমে আপনাকে রিপোজিটরি যুক্ত করতে হবে নিচের কমান্ডের মাধ্যমে- ``` sudo apt-get install software-properties-common sudo add-apt-repository ppa:ondrej/php5-5.6 ``` এবার রিপোজিটরি লিস্টিং আপডেট করুন, এবং কোন প্যাকেজ আপগ্রেড করার থাকলে সেটিও করুন। এই আপগ্রেড অবশ্য অপশনাল। আপনি চাইলে না করলেও পারেন। ``` sudo apt-get update sudo apt-get upgrade ``` এবার নিচের কমান্ডের মাধ্যমে পিএইচপি ৫.৬ ইনস্টল করুন। তবে আপনার পিসিতে যদি আগে থেকেই পিএইচপি ইনস্টল করা থাকে তাহলে আপগ্রেড কমান্ডের মাধ্যমে অলরেডি পিএইচপি ৫.৬ ইনস্টল হয়ে যাওয়ার কথা। ``` sudo apt-get install php5 ``` এবার চেক করতে টার্মিনালে লিখুন- ``` php -v ``` তবে এ ধরনের থার্ড পার্টি পোর্টগুলোতে বাগ থাকতে পারে। তাই আমার পরামর্শ প্রোডাকশনে পিএইচপির এই ভার্সন ব্যবহার করার দরকার নেই। তবে আপনি আপনার ডেভেলপমেন্ট মেশিনে এটি ইনস্টল করতে পারেন। প্রোডাকশনে আপগ্রেড করার জন্য উবুন্টু অফিশিয়াল রিলিজের জন্য অপেক্ষা করুন। --- # Upgrading a project from Laravel 5.0 to 5.1 > Complete guideline to upgrade a Laravel 5.0 project to Laravel 5.1 Published: 2015-06-11 URL: https://milon.im/post/upgrading-a-project-from-laravel-5-0-to-5-1.md Laravel just released it's first LTS relase two days back. I was very excited about this release and can't wait to upgrade my existing project to the latest version. I have just updated a laravel 5.0 project to laravel 5.1\. It was quiet a big project around 10 thousand line and 6 people working it. It was on latest iteration on laravel 5.0 branch which is 5.0.33\. It's a fairly simple task and took around 50 minutes. Let's get started. **Take Backup** At first take a backup of your existing project so that if anything goes wrong you could restore. If you are using git you could make a different brunch of your update- ``` git checkout -b update ``` **Update bootstrap/autoload.php file** Previouslycompiled file was in `/storage/framework` directory but in 5.1 it is in `/bootstrap/autoload` directory. So, change the `$compiledPath` variable to this- ``` $compiledPath = __DIR__.'/cache/compiled.php'; ``` **Create bootstrap/cache directory** Then create `bootstrap/cache` directory and give write permission to it, becasue laravel will put it's `compiled.php`, `routes.php`, `config.php`, and `services.json` file in it. To do this run below command to console- ``` sudo chmod 755 -R bootstrap/cache ``` Then create a .gitignore file in this directory and put following content in it- ``` * !.gitignore ``` **Authentication** If you are not using laravel's default authentication scaffold then leave this section. If you are using then at first go to `app/Http/Controllers/Auth/AuthController.php` file. At first remove two dependencies from the controller. Then go to `app/Services/Registrar.php` file and copy validator and create method from it and paste it to `AuthController`. Then also import `App\User` and `Illuminate\Support\Facade\Validator` at the top of this class. After that delete `Registrar` class entirely. After doing all those things `AuthController` will be look like this- ``` middleware('guest', ['except' => 'getLogout']); } /** * Get a validator for an incoming registration request. * * @param array $data * @return \Illuminate\Contracts\Validation\Validator */ public function validator(array $data) { return Validator::make($data, [ 'name' => 'required|max:255', 'email' => 'required|email|max:255|unique:users', 'password' => 'required|confirmed|min:6', ]); } /** * Create a new user instance after a valid registration. * * @param array $data * @return User */ public function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => bcrypt($data['password']), ]); } } ``` Also remove the dependency from PasswordController's constructor method. Those are no longer needed. **Validation** If you don't override any of the default validator method then you are good to go to the next section. If you do override `formatValidationErrors` method on your `BaseController` class then typehint `Illuminate\Contracts\Validation\Validator` class to the instead of create an instance of `Illuminate\Validation\Validator` class. Do the same thing for `formatErrors` method also. Typehint `Illuminate\Contracts\Validation\Validator` class instead of create an instance of `Illuminate\Validation\Validator` class. **Eloquent** Eloquent's create method now can applied with no parameter. So, If you are overriding this class, make sure you pass an empty array as a default parameter to this method. This will be look like this- ``` public static function create(array $attributes = []) { // Your custom implementation } ``` If you are overriding the find method in your own models and calling parent::find() within your custom method, you should now change it to call the find method on the Eloquent query builder. This will look like this- ``` public static function find($id, $columns = ['*']) { $model = static::query()->find($id, $columns); // ... return $model; } ``` **Date Formatting** In 5.0 you could change the format of storage of date field by override `getDateFormat` method. This is still applicble but you could also use the more cleaner way to do this. Simply specify a `$dateFormat` property to the model declaring the fields you want in date format and you are good to go. This is also applied for serializing model to array or JSON. You can override `serializeDate(DateTime $date)` method to do this. **The Collection Class** I use the collection class a lot, I think you also do, as eloquent and query builder returns collection. Previously the sort method modify the existing collection. But from 5.1 it will return a completely new instance of collection. Take a look- ``` $collection = $collection->sortBy('name'); ``` The groupBy method now returns an instance of collection for each of it's item. You could map over the collection for getting previous format- ``` $collection->groupBy('type')->map(function($item) { return $item->all(); }); ``` `lists` method now return collection instead of array. To get array form that- ``` $collection->lists('id')->all(); ``` **Commands & Handlers** `Commands` are now renamed to `Jobs` and `Handlers` are now renamed to `Listeners`. But This change is backward compatible. So, you are good to go without modifying it, but my suggesstion is rename the files and fix namespaces for your commands and events classes. **Tests** Just add a protected `$baseUrl` property to `App\TestCase` class and you are good to go. ``` protected $baseUrl = 'http://localhost:8000'; ``` **Amazon Web Services SDK** If you are using amazon web service then update you sdk by defining the version to `composer.json` file and do a `composer update`. ``` "league/flysystem-aws-s3-v3": "~1.0" ``` **Update** After doing all these things go to `composer.json` file and change the require object like this- ``` "require": { "php": ">=5.5.9", "laravel/framework": "5.1.*" }, "require-dev": { "fzaninotto/faker": "~1.4", "mockery/mockery": "0.9.*", "phpunit/phpunit": "~4.0", "phpspec/phpspec": "~2.1" }, ``` Then run following two command to the console- ``` composer update composer dump-autoload -o ``` **Depredations** There are also some depredations with the release of 5.1\. You should take a look at release guide section at the documentation and fix it gradually. This will be removed on Laravel 5.2 which will be released on December, 2015. Happy Coding... --- # লারাভেল ডিফার্ড সার্ভিস প্রোভাইডার > লারাভেলের ডিফার্ড সার্ভিস প্রোভাইডার কি, কেন এবং কিভাবে? Published: 2015-06-08 URL: https://milon.im/post/laravel-defered-service-provider.md আমরা অনেক সময়ই লারাভেল অ্যাপ্লিকেশন তৈরির সময় সার্ভিস প্রোভাইডার তৈরি করে থাকি। এই সার্ভিস প্রোভাইডারগুলি লারাভেল সার্ভিস কনটেইনারে রেজিস্টার করা থাকে। লারাভেল যখন কোন রিকোয়েস্ট গ্রহণ করে তখন এই সার্ভিস কনটেইনার ইনিশিয়ালাইজ হয়, এবং রিকোয়েস্টকে প্রসেস করতে যদি সার্ভিসের প্রয়োজন পড়ে সেটা কাজ করে রিকোয়েস্টকে প্রসেস করে রেসপন্স তৈরি করতে সাহায্য করে। সহজ একটা উদাহরন দেখুন। ধরুন আপনি একটি টু-ডু অ্যাপের একজন রেজিস্টার ইউজার, এবং আপনি আপনার টু-ডু লিস্ট দেখতে চাইছেন। এক্ষেত্রে লারাভেলের কাছে রিকোয়েস্ট করার পর লারাভেল সার্ভিস কনটেইনারের কাছে রিকোয়েস্টটা পাঠায় এবং সেটি তখন দেখে যে আপনার রিকোয়েস্টটিকে প্রসেস করতে ইলোকোয়েন্ট সার্ভিসটির প্রয়োজন। তখন ইলোকোয়েন্ট আপনার রিকোয়েস্টটি প্রসেস করবে। এরপর ধরুন আপনাকে একটি নোটিফিকেশন দেয়া প্রয়োজন। সেক্ষেত্রে সার্ভিস কনটেইনার সেসন সার্ভিস প্রোভাইডারের সাহায্য নেবে। এক্ষেত্রে দেখা যাচ্ছে একটা রিকোয়েস্ট প্রসেস করতে সবগুলো সার্ভিস প্রোভাইডারের দরকার নেই। হয়ত ২-৩টা প্রোভাইডারের প্রয়োজন। সেক্ষেত্রে আপনি চাইলে ডিফার্ড সার্ভিস প্রোভাইডার ব্যবহার করতে পারবেন। নাম দেখেই নিশ্চয়ই বুঝতে পারছেন, এই ডিফার্ড সার্ভিস প্রোভাইডার শুধুমাত্র যখন প্রয়োজন তখনই লোড হবে। অন্যান্য রিকোয়েস্টে এটি লোড হবে না। এটি আপনার অ্যাপ্লিকেশন পারফরমেন্স বহুগুনে বাড়িয়ে দিতে পারে। এখন কথা হচ্ছে কিভাবে এই ডিফার্ড সার্ভিস প্রোভাইডার তৈরি করবেন? সেটিও খুব সহজ। সাধারন সার্ভিস প্রোভাইডারের মতই একটি আর্টিসান কমান্ডের মাধ্যমে আপনি এটি তৈরি করতে পারবেন। এর জন্য টার্মিনালে নিচের কমান্ডটি লিখুন- ``` php artisan make:provider TestServiceProvider ``` এর ফলে আপনার অ্যাপ্লিকেশনের `app/Providers` ফোল্ডারের মধ্যে একটি নতুন ফাইল তৈরি হবে `TestServiceProvider.php` নামে। এটি দেখতে হবে এরকম- ``` লারাভেলের ৫.১ এবং মাইসিক্যুয়েল ব্যবহার করে তৈরি করা টু-ডু লিস্ট এ্যাপ্লিকেশন Published: 2015-06-07 URL: https://milon.im/post/laravel-todo-app.md আমার বইটা প্রকাশিত হবার পর থেকেই অনেকের কাছ থেকেই একটা অনুরোধ পেয়েছি। সেটা হচ্ছে আমার বইয়ে একটা ডেমো অ্যাপের দরকার ছিল, কিন্তু সেটা দেয়া হয় নি। তাই সবার অনুরোধ রাখতে আমি একটা সিম্পল টু-ডু অ্যাপ তৈরি করেছি। এই অ্যাপটি তৈরি করতে আমি ব্যবহার করেছি লারাভেল ফ্রেমওয়ার্ক ৫.১ ভার্সন এবং মাইসিক্যুয়েল। এই অ্যাপটির কোড পাবেন [গিটহাবে](https://github.com/milon/laravel-todo)। এখানে অথেনটিকেশন, সিম্পল CRUD(Create, Read, Update, Delete) অপারেশন, রিসোর্সফুল রাউটিং, ফরম মডেল বাইন্ডিং, ফরম রিকোয়েস্ট, ফ্ল্যাশ ম্যাসেজ, পেজিনেশন সহ কিভাবে আপনি আপনার কোড গুছিয়ে লিখতে পারবেন, সে ব্যাপারে আলোকপাত করা হয়েছে। ![Todo App - Landing Page](/assets/images/posts/todo-01.png) ![Todo App - Sign In Page](/assets/images/posts/todo-02.png) ![Todo App - Registration Page](/assets/images/posts/todo-03.png) ![Todo App - Todo List Page](/assets/images/posts/todo-04.png) ![Todo App - Create New Todo Page](/assets/images/posts/todo-05.png) ![Todo App - User Profile Page](/assets/images/posts/todo-06.png) অ্যাপটি আপনার পিসিতে রান করতে হলে প্রথমেই গিটহাবে রিপোজিটরিটি ফর্ক করুন, তারপর ক্লোন করতে নিচের কমান্ডটি দিন- ``` git clone https://github.com/milon521/laravel-todo.git ``` এরপর ঐ ডিরেক্টরিতে প্রবেশ করুন নিচের কমান্ডটির মাধ্যমে- ``` cd laravel-todo ``` এরপর .env ফাইলটি তৈরি করুন নিচের কমান্ডটির মাধ্যমে- ``` cp .env.example .env ``` এবার .env ফাইলে আপনার প্রয়োজনীয় পরিবর্তন করে নিন। শুধুমাত্র DB_USERNAME এবং DB_PASSWORD এই দুইটি ফিল্ড পরিবর্তন করলেই হয়ে যাওয়ার কথা। তারপর আপনি নতুন একটি ডেটাবেজ তৈরি করুন todos নামে। এরপর আপনি আপনার প্রয়োজনীয় ডিপেন্ডেন্সি ডাউনলোড করুন নিচের কমান্ডটির মাধ্যমে- ``` composer update ``` এবার আপনি নিচের কমান্ডটির মাধ্যমে আপনার ডেটাবেজ মাইগ্রেশন করে নিন- ``` php artisan migrate ``` সবশেষে আপনি storage ফোল্ডারের রাইট পারমিশন দেন এভাবে- ``` sudo chmod 777 -R /storage ``` ব্যাস হয়ে গেছে। এবার প্রজেক্টটি রান করতে টার্মিনালে লিখুন- ``` php artisan serve ``` এবার আপনি আপনার ব্রাউজারে `‌http://localhost:8000‌` ইউআরএলে গেলে প্রজেক্টটি দেখতে পারবেন। আপনারা যদি চান তাহলে আমি কিভাবে প্রজেক্টি তৈরি করলাম সেটি স্টেপ বাই স্টেপ লিখবো। সেক্ষেত্রে আমাকে আপনাদের ব্যাপারটি জানাতে হবে। --- # Story behind my book > The underlying story behind my first ever published book. Published: 2015-06-04 URL: https://milon.im/post/story-behind-my-book.md I have been facing a specific question last few days, after publishing my book. The question is how do I publish my book. This post is the answer of that very question. You know I write blog posts and tutorials on different computer programming related topics. Last one odd year I have working on Laravel PHP Framework on my daily job. So, I decided to write a blog post series on Laravel. The latest version of Laravel was 4.2 then. So, I decided to write on Laravel 4.2\. But within one week Taylor Otwell declared that next version of Laravel will be a major release version 5.0\. So, then I started to look up on github commit and write accordingly. Ohh, I don't published any blog post as I was planning the whole series at a time. Then one of colleague suggested me to publish this as a book. Then when my blog series is almost done, then I go a renowned publisher of Bangladesh, but he ask money for publishing the book. I was shocked, I told him, rather I will prefer to publish this as a blog post series than to publish it with my own money. That night I talked with Tamim Shahriar Subeen Bhai through facebook chat. He told me not to publish the blogs until he read it. After reading the manuscript he decided to publish it. Then I started to working with a new spirit for publishing the book. Me, Tahmid Rafi Bhai and Subeen Bhai working very hard to publish the book. In the mean time, Taylor declared Laravel 5.1 will be a Long Term Support(LTS) release. So, I updated my book for the 5.1 version, and then send it to proof reader. After that, me and Rafi Bhai do page setup for the book. Then within one week the book published on 26th May, 2015\. Don't I forget to mention Laravel 5.1 LTS will be released on 9th June, 2015\. So, If you are go with my book for learning Laravel, you will go with the most cutting edge features of Laravel. My book took best seller position of [www.rokomari.com](https://www.rokomari.com). Thank you all who ever make it possible. Wish me luck. --- # My book took the first place of bestseller list of rokomari.com > Laravel PHP Web Framework hit #1 on the Rokomari bestseller list shortly after release. Published: 2015-06-02 URL: https://milon.im/post/my-book-took-the-first-place-of-bestseller-list-of-rokomari-com.md My book **Laravel PHP Web Framework** was released on 26th May, 2015\. This is my first book, and I am very happy to see my book on [www.rokomari.com](http://www.rokomari.com)'s bestseller list. ![Bestseller List](/assets/images/posts/bestseller-list.jpg) I want to thank you all who made this done. Specially Subeen Bhai and Rafi Bhai. Those who are still don't get my book, you could get it from [here](http://www.rokomari.com/book/100634). The book is priced 350 taka, but rokomari sell it at a reduced price. You could also get this book from Haque Library, 31, Babupura, Nilkhet, Dhaka. Thanks again for supporting me. Hope you will keep supporting me continuously. --- # লারাভেল বইয়ের প্রিন্টিং মিসটেক প্রসঙ্গে > আমার প্রকাশিত বইয়ের প্রিন্টিং মিসটেক সম্পর্কে আমার বক্তব্য। Published: 2015-05-29 URL: https://milon.im/post/about-printing-mistake-of-laravel-book.md আমার প্রকাশিত প্রথম বই **লারাভেল পিএইচপি ওয়েব ফ্রেমওয়ার্ক**-এ অনিচ্ছাসত্ত্বেও একটা প্রিন্টিং মিসটেক হয়ে গেছে। বইয়ের প্রথম অধ্যায়ের "কনস্ট্রাক্টর ইনজেকশন" অংশের(পৃষ্ঠা নাম্বার ১৭) কোডে কয়েকটি লাইন বাদ পড়ে গেছে। পাঠকের যাতে বুঝতে অসুবিধা না হয় সেজন্য সেই অংশটি আমি এখানে দিয়ে দিচ্ছি। ``` use Book; use BookShelf; class Library{ $protected $book; $protected $bookShelf; public function __construct(Book $book, BookShelf $bookShelf){ $this->book = $book; $this->bookShelf = $bookShelf; } } ``` এ অনাকাঙ্খিত ভুলের জন্য আমি পাঠকের নিকট ক্ষমাপ্রার্থী। পরবর্তী সংস্করণে এ ভুল শুধরে দেয়া হবে। --- # Laravel 5.1 Database Factory > What is database factory, how to use it? Published: 2015-05-29 URL: https://milon.im/post/laravel-5-1-database-factory.md Earlier versions of laravel comes with a system for seeding dummy data on database. Traditionaly you just create a class extending laravel's DatabaseSeeder class. This would look like this- ``` insert([ 'name' => str_random(10); 'email' => str_random(10).'@gmail.com', 'password' => bcrypt('secret'), ]); } } ``` Then you can run this command for seed in database- ``` php artisan db:seed ``` Instead of using creating query builder, you could also called eloquent. In that case, run method will look like this- ``` public function run(){ \App\User::create([ 'name' => str_random(10); 'email' => str_random(10).'@gmail.com', 'password' => bcrypt('secret'), ]); } ``` You could also use a package called faker with it. Faker will generate bunch of different things automatically for you like- name, email, phone number, paragraph, sentence, date and much more. In that case UserTableSeeder class will look like this- ``` insert([ 'name' => $faker->name; 'email' => $faker->email, 'password' => bcrypt('secret'), ]); } } ``` For more entry you could use loop and each time faker would create different entry for you. But using laravel's new feature model factory, this could be much more simpler. Take a look- ``` class UserTableSeeder extends Seeder { public function run() { factory('App\User', 50)->create(); } } ``` Couldn't be much simpler than that, right? You could also use make method that will create users, but won't persist them in database. This method is very helpful for testing. Let talk them another day, as it is out of scope of today's topic. Now you could wonder, how laravel knows that we should create 50 users, and how it also know the database schema and what to seed? I think if you already noticed that laravel 5.1 comes with a new folder called factory in database folder and by default there is a file called ModelFactory. Let's look at this file- ``` $factory->define('App\User', function ($faker) { return [ 'name' => $faker->name, 'email' => $faker->email, 'password' => str_random(10), 'remember_token' => str_random(10), ]; }); ``` Here we see, laravel creates a factory defination for App\User model and it passes a faker object, that we use earlier. We could also create other defination and also create another file in this directory. But if you create new file, you should run this command- ``` composer dump-autoload ``` This needed to be done because in version 5.1 laravel autoload database folder with classmap. You could take a look composer.json file. Happy coding... --- # bower এর ব্যবহার > কেন এবং কিভাবে bower ব্যবহার করবেন? Published: 2015-05-11 URL: https://milon.im/post/uses-of-bower.md প্রথমেই একটা অভিজ্ঞতা শেয়ার করি। কিছুদিন আগে একটা প্রজেক্টে কাজ করার সময় দেখলাম আমি জেকুয়েরি ডেটাটেবিল প্লাগিনের যে ভার্সন ব্যবহার করেছিলাম তার একটা আপডেট ভার্সন রিলিজ পেয়েছে, যেখানে সর্টিং সুবিধা যুক্ত হয়েছে। আপডেট করার সময় মনে হলো যদি ক্লায়েন্ট সাইড ডিপেন্ডেন্সি ম্যানেজ করার জন্য কম্পোজারের মত কোন টুল থাকতো? সার্চ করতেই খোজ পেলাম বাওয়ারের। বাওয়ার টুইটারের তৈরি করা ক্লায়েন্ট সাইট ডিপেন্ডেন্সি ম্যানেজমেন্ট টুল। এটি আসলে একটি নোড প্যাকেজ। সুতরাং বাওয়ার ব্যবহার করতে হলে আপনার পিসিতে অবশ্যই নোডজেএস ইনস্টল থাকা লাগবে। নোড ইনস্টল করলে এর সাথে সাথে এর প্যাকেজ ম্যানেজার `npm`(নোড প্যাকেজ ম্যানেজার)ও ইনস্টল হয়। বাওয়ার ইনস্টল করার জন্য আপনাকে নিচের কমান্ডটি টার্মিনালে লিখতে হবে- ``` npm install -g bower ``` ইনস্টল হয়ে গেলে এটি চেক করার জন্য টার্মিনালে লিখুন- ``` bower -v ``` এবার আপনি বাওয়ার ব্যবহার করতে পারবেন, ঠিক যেভাবে npm বা composer ব্যবহার করেন। ধরুন আপনি জেকুয়েরি ইনস্টল করতে চান। যেমন- ``` bower install jquery ``` এবার ধরুন আপনি বুটস্ট্র্যাপ ইনস্টল করতে চান। এরজন্য আপনাকে লিখতে হবে- ``` bower install bootstrap ``` এখন বুটস্ট্র্যাপ যেহেতু জেকুয়েরির উপর নির্ভরশীল, তাই বুটস্ট্র্যাপ ইনস্টল করলে এর যত ডিপেন্ডেন্সি আছে সেগুলিও ইনস্টল হয়ে যাবে। এখন ধরুন আপনি যে প্যাকেজগুলি ইনস্টল করেছেন, সেগুলির লিস্ট একটা ফাইলে সেভ করে রাখতে চান। এটা আপনি করতে পারবেন `bower.json` নামের ফাইলে। এই ফাইলটি তৈরি করতে লিখুন- ``` bower init ``` এখন আপনি যে প্যাকেজটি ইনস্টল করেছেন, সেটি যদি বাওয়ার ফাইলো সেভ করে রাখতে চান, তাহলে লিখুন- ``` bower install jquery --save ``` এই --save এর মাধ্যমে আপনি ডিপেন্ডেন্সি হিসেবে যোগ করতে পারবেন। আপনি চাইলে ডেভেলপার ডিপেন্ডেন্সিতেও যুক্ত করতে পারবেন এভাবে- ``` bower install jquery --save-dev ``` বাই ডিফল্ট বাওয়ার তার সমস্ত প্যাকেজ ইনস্টল করে bower_components নামে ফোল্ডারে। আপনি চাইলে এটি পরিবর্তন করতে পারবেন .bowerrc ফাইলের মাধ্যমে। এটি একটি জেসন ফাইল, এটি দেখতে হবে অনেকটা এরকম- ``` { "directory": "app/components/", "analytics": false, "timeout": 120000, "registry": { "search": [ "http://localhost:8000", "https://bower.herokuapp.com" ] } } ``` বাওয়ার এপিআই সম্পর্কে বিস্তারিত জানার জন্য আপনি সাইটটি ভিজিট করতে পারবেন। --- # লারাভেল ৫: ইলোকোয়েন্ট এট্রিবিউট কাস্টিং > লারাভেল ৫ এর ইলোকোয়েন্ট এট্রিবিউট কাস্টিং এর অদ্যোপান্ত। Published: 2015-03-24 URL: https://milon.im/post/laravel-5-eloquent-attribute-casting.md আমরা জানি লারাভেলের ইলোকোয়েন্ট ওআরএম এ কোন কোয়েরি চালালে যে ভ্যালু রিটার্ন করে সেটা সবসময়ই স্ট্রিং হিসেবে থাকে। এতে করে একটা সমস্যা প্রায়ই দেখা যায়। যেমন ধরুন, আমরা নিচের কোয়েরিটা চালালাম User নামের মডেলে- ``` $user = User::find($id); ``` ধরি আমাদের ইউজার টেবিলে শুধুমাত্র নাম এবং এক্টিভেটেড ফ্লাগ কলাম আছে। সেক্ষেত্রে এই ইউজারকে যদি আমরা ডাম্প করি তাহলে নিচের মত আউটপুট দেখতে পাবো- ``` { "id" => "1", "name" => "John Doe", "activated" => "0" } ``` এক্ষেত্রে একটি সাধারন সমস্যা হচ্ছে ইউজার এক্টিভেটেড কিনা সেটি যদি আমরা চেক করি তাহলে সেক্ষেত্রে দেখা যাবে- ``` echo ($user.activated)? "Yes" : "No"; //output: Yes ``` এক্ষেত্রে আউটপুট আসবে Yes যদিও No আউটপুট আসা উচিৎ ছিল। এর কারন এক্টিভেটেড ফ্লাগটি স্ট্রিং হিসেবে আছে। ফ্লাগটি যদি বুলিয়ান ভ্যালু হিসেবে থাকতো তাহলে আর এই সমস্যাটা হতো না। লারাভেল ৪.* এ আমরা এক্সেসর এবং মিউটেটর ব্যবহার করে এই সমস্যার সমাধান করতে পারতাম। মডেল ক্লাসে নিচের মেথডটি যুক্ত করে আমরা ভ্যালুটিকে বুলিয়ানে কাস্টিং করতে পারতাম- ``` public function getActivatedAttribute($value){ return (boolean) $value; } ``` লারাভেল ৫ এ আপনি একইভাবে এট্রিবিউট কাস্টিং করতে পারবেন। এছাড়া আরো একটি সহজ উপায় যুক্ত হয়েছে লারাভেল ৫ এ। সেটি হচ্ছে মডেলে $casts নামে একটি এসোসিয়েটিভ এরে যোগ করে সেটিতে ডেটাটাইপ ডিক্লেয়ার করে দেয়া। যেমন উপরের উদাহরনটিকে যদি নতুন পদ্ধতিতে কাস্টিং করতে চাই সেক্ষেত্রে লিখতে হবে- ``` proteced $casts = [ 'activated' => 'boolean' ]; ``` শুধুমাত্র বুলিয়ানেই কাস্টিং করতে পারবেন তা না। boolean ছাড়াও আপনি integer, real, float, double, string, boolean, object এবং array তে কাস্ট করতে পারবেন। এক্ষেত্রে বলে রাখা ভালো এরে কাস্টিং শুধুমাত্র ব্যবহৃত হয় যখন কোন কলামে জেসন সিরিয়ালাইজড ডেটা সেভ করা হয়। যেমন ধরুন আমাদের উদাহরনের ইউজার টেবিলে যদি অপশন নামে একটি কলাম থাকতো, এবং সেটিতে যদি সিরিয়ালাইজ ডেটা সেভ করা হতো তাহলে সেটি করা হতো এভাবে- ``` $user = User::find($id); $user->options = [ 'email' => 'john@example.com', 'age' => 20 ]; $user->save(); ``` এক্ষেত্রে ইউজারকে ডাম্প করলে আমরা অপশনের জায়গায় একটি সিরিয়ালাইড জেসন ডেটা পেতাম। কিন্তু আমরা যদি $casts এরেতে অপশন হিসেবে এরে সিলেক্ট করি সেক্ষেত্রে মডেল ডেটা রিটার্ন করার সময় অটোমেটিক আউটপুটকে ডিসিরিয়ালাইজ করবে। --- # লারাভেল ৫ এ প্যাকেজ ডেভেলপমেন্ট > কিভাবে লারাভেল ৫ ফ্রেমওয়ার্কের জন্য প্যাকেজ তৈরি করবেন তার বিস্তারিত। Published: 2015-03-23 URL: https://milon.im/post/package-development-in-laravel-5.md লারাভেল ৪.* এ `"illuminate/workbench"` প্যাকেজ ব্যবহার করে খুব সহজেই আমরা লারাভেলের জন্য প্যাকেজ ডেভেলপ করতে পারতাম। কিন্তু লারাভেল ৫ এ সেটিকে লারাভেলের কোর থেকে বাদ দেয়া হয়েছে। আসলে টেইলর অটোয়েল(লারাভেলের জনক) মনে করেন, প্যাকেজগুলো ফ্রেমওয়ার্ক ইন্ডিপেন্ডেন্ট হওয়া জরুরী। তাই তিনি এ প্যাকেজটিকে লারাভেলের কোর থেকে বাদ দিয়েছেন। তবে আমরা চাইলে এ প্যাকেজটি ব্যবহার করে খুব সহজেই লারাভেল ৫ এর জন্য প্যাকেজ তৈরি করতে পারি। এরজন্য প্রথমেই যা করতে হবে সেটি হচ্ছে লারাভেল ইনস্টলের পর `"illuminate/workbench"` প্যাকেজের `"dev-develop"` ব্রাঞ্চটিকে আপনার প্রজেক্টে পুল-ইন করে নিতে হবে। এটি করতে আপনি কম্পোজার ফাইলের রিকোয়ার অংশে নিচের লাইনটি যুক্ত করুন- ``` "require": { "laravel/framework": "5.0.*", "illuminate/workbench": "dev-master" }, ``` এরপর টার্মিনালে নিচের কমান্ডটি দিন- ``` composer update ``` এরপর `config/app.php` ফাইলের `providers` এরেতে নিচের লাইনটি যুক্ত করতে হবে- ``` 'providers' => [ ..., 'Illuminate\Workbench\WorkbenchServiceProvider', ] ``` এবার আপনার প্রজেক্টের কনফিগ ডিরেক্টরিতে workbench.php নামে একটি নতুন ফাইল তৈরি করুন এবং সে ফাইলটিতে নিচের অংশটুকু যুক্ত করে দিন- ``` '', /* |-------------------------------------------------------------------------- | Workbench Author E-Mail Address |-------------------------------------------------------------------------- | | Like the option above, your e-mail address is used when generating new | workbench packages. The e-mail is placed in your composer.json file | automatically after the package is created by the workbench tool. | */ 'email' => '', ]; ``` এই ফাইলের নাম এবং পাসওয়ার্ড অংশে প্যাকেজ রাইটারের নাম এবং ইমেইল এড্রেস লিখুন। এবার আপনার কাজ শেষ। নতুন প্যাকেজ ডেভেলপমেন্ট শুরু করতে টার্মিনালে নিচের কমান্ডটি লিখুন- ``` php artisan workbench vendor/package ``` এই vendor এবং package এর জায়গায় আপনি আপনার প্যাকেজের ভেন্ডরের নাম এবং প্যাকেজের নাম লিখবেন। কমান্ডটি দেয়ার পরে দেখবেন আপনার প্রজেক্টের রুট ডিরেক্টরিতে workbench নামে একটি ফোল্ডার তৈরি হয়েছে, এবং এই ফোল্ডারের ভেতরে আপনার প্যাকেজের জন্য একটি ফোল্ডার এবং অন্যান্য স্ক্যা-ফোল্ডিং ফাইল তৈরি হয়ে গেছে। ব্যস, শুরু করে দিন প্যাকেজ ডেভেলপমেন্ট। --- # লারাভেল অ্যাপ্লিকেশন থেকে আর্টিসান কমান্ড কল করা > লারাভেল অ্যাপ্লিকেশনের ভেতর থেকে আর্টিসান কমান্ড কল করার পদ্ধতি। Published: 2014-12-28 URL: https://milon.im/post/calling-artisan-command-from-your-application.md আমরা যারা লারাভেলের সাথে পরিচিত, তারা প্রায় সবাই জানি লারাভেল আর্টিসান নামের একটি কমান্ড লাইন ইউটিলিটি সহ এসেছে যেটা সিম্ফোনীর কনসোল কম্পোনেন্টের উপর ভিত্তি করে তৈরি করা। আমরা সবাই এটা ব্যবহার করি টার্মিনাল বা কনসোল থেকে। অনেকেই জানি না যে লারাভেল অ্যাপ্লিকেশন থেকেও এই আর্টিসান কমান্ড কল করা যায়। চলুন দেখি কিভাবে এটা করে। ধরি আমরা নিচের কমান্ডটি অ্যাপ্লিকেশন থেকে কল করতে চাই- ``` artisan migrate --env=test --path=app/database/migrations/test ``` এটা আমরা অ্যাপ্লিকেশনের কোন মেথড থেকে এভাবে কল করতে পারি- ``` Artisan::call('migrate', [ '--env' => 'test', '--path' => 'app/database/migrations/test' ]); ``` --- # লারাভেল ৫ এ flip/whoops প্যাকেজের ব্যবহার > কিভাবে flip/whoops প্যাকেজের ব্যবহার করবেন লারাভেল ৫-এ। Published: 2014-11-03 URL: https://milon.im/post/uses-of-flips-whoops-in-laravel-5.md **আপডেট** > এই ব্লগটি প্রথমে যখন লেখা হয়েছিল, তখন লারাভেল ৫ রিলিজ হয় নি। রিলিজের পর দেখা গেল বেটা ভার্সনে লারাভেল যেভাবে এরর হ্যান্ডেল করতো তা পরিবর্তিত হয়েছে। এখানে নতুন উপায়ে কিভাবে হুপস প্যাকেজ ব্যবহার করতে পারবেন তা দেখানো হয়েছে। প্রথমেই টার্মিনালে লিখুন- ``` composer require filp/whoops:~1.0 ``` এরপর কম্পোজার আপডেট কমান্ড দিন। এবার `app/Exceptions/Handler.php` ফাইলে যান এবং এই ক্লাসের `render()` মেথডটিকে নিচের মত করে এডিট করুন- ``` /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response */ public function render($request, Exception $e) { if ($this->isHttpException($e)) { return $this->renderHttpException($e); } if (config('app.debug')) { $whoops = new \Whoops\Run; $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler()); return new \Illuminate\Http\Response( $whoops->handleException($e), $e->getStatusCode(), $e->getHeaders() ); } return parent::render($request, $e); } ``` ব্যাস আপনার কাজ হয়ে গেছে। এবার আপনি আপনার এরর স্ক্রীনে হুপস দেখতে পারবেন। **পুরনো পদ্ধতি** আপনারা নিশ্চয়ই প্যাকেজিস্ট এর `flip/whoops` প্যাকেজের সাথে পরিচিত। এই প্যাকেজটিকে লারাভেল ৪.* এ ডিফল্ট এরর পেজ হিসেবে ব্যবহার করা হতো। কিন্তু লারাভেল ৫ এ এই প্যাকেজটিকে রিমুভ করা হয়েছে। যদিও আমি নিজে মনে করি এটি এখন পর্যন্ত পিএইচপির জন্য বেস্ট এরর দেখানোর প্যাকেজ। এটি আপনি চাইলে খুব সহজেই লারাভেল ৫ এ ফিরিয়ে আনতে পারেন। আপনাকে প্রথমেই `composer.json` ফাইলটি আপডেট করতে হবে। আপনি এর `require-dev` অপশনে নিচের লাইনটি যুক্ত করুন- ``` "filp/whoops": "~1.0" ``` এবার আপনি টার্মিনালে লিখুন- ``` composer update ``` আপনি whoops প্যাকেজটি ডাউনলোড হওয়ার পর টার্মিনালে লিখুন- ``` php artisan make:provider ErrorServiceProvider ``` এই কমান্ডটি আপনার `app/Providers` ফোল্ডারে এরর সার্ভিস প্রোভাইডার নামে একটি ফাইল তৈরি করবে। আপনি সেই ফাইলটিকে নিচের মত করে এডিট করুন- ``` pushHandler(new PrettyPageHandler); $whoops->register(); } /** * Register the application services. * * @return void */ public function register() { // } } ``` আপনার এরর সার্ভিস প্রোভাইডার তৈরি হয়ে গেছে। এবার একে রেজিস্টার করুন। এর জন্য `config/app.php` ফাইলের প্রোভাইডার এরেতে নিচের লাইনটি যুক্ত করুন- ``` 'providers' => [ ..., 'App\Providers\ErrorServiceProvider', ], ``` ব্যাস, আপনি whoops প্যাকেজ লারাভেল ৫ এ ইন্টিগ্রেট করে ফেলেছেন। টেস্ট করার জন্য রাউট ফাইলে নিচের কোডটি লিখুন- ``` $router->get('/', function(){ throw new \Exception('Whoops Test...'); }); ``` এবার আপনি যদি আপনার রুট রাউট ভিজিট করেন তাহলে নিচের মত আউটপুট দেখতে পাবেন। ![Whoops](/assets/images/posts/whoops.webp) --- # লারাভেল ইনস্টলেশন > কিভাবে লারাভেল ফ্রেমওয়ার্ক ইনস্টল করবেন? Published: 2014-08-08 URL: https://milon.im/post/laravel-installation.md লারাভেল অত্যন্ত চমৎকার একটি পিএইচপি ফ্রেমওয়ার্ক। এর রয়েছে অসাধারণ সব ফিচার। আমি মূলত কোডইগনিটার ডেভেলপার, কিন্তু লারাভেলের চমৎকার ফিচারগুলো আমাকে এতই মুগ্ধ করেছে যে আমি কোডইগনিটার বাদ দিয়ে আমার ডেভেলপমেন্টের জন্য লারাভেল বেছে নিয়েছি। এর ফিচারগুলো সম্পর্কে বলতে গেলে আর একটা পোস্ট দিতে হবে। সেটা অন্য কোন দিন হবে, আজকে দেখবো কিভাবে আপনি আপনার পিসিতে লারাভেল পিএইচপি ফ্রেমওয়ার্ক ইনস্টল করবেন। লারাভেল আপনার পিসিতে দুইভাবে ইনস্টল করতে পারবেন। প্রথমত পারবেন লারাভেল ইনস্টলারের মাধ্যমে আর দ্বিতীয়ত কম্পোজারের মাধ্যমে। **লারাভেল ইনস্টলার** প্রথমেই আপনাকে লারাভেলের অফিশিয়াল সাইট থেকে এর `.phar` আর্কাইভ ডাউনলোড করে নিতে হবে। কাজের সুবিধার জন্য ফাইলটিকে রিনেম করে laravel করুন। এবার আপনি যদি `*nix` ব্যবহারকারী হয়ে থাকেন তাহলে ফাইলটিকে `urs/local/bin` ডিরেক্টরিতে মুভ করুন। আর যদি উইন্ডোজ ব্যবহারকারী হয়ে থাকেন তাহলে ফাইলটিকে যেখানে সেভ করেছেন, সেটিকে আপনার পাথ ভ্যারিয়েবলে যোগ করুন। এরপরের কাজ খুবই সোজা। কমান্ড লাইন থেকে যেখানে লারাভেল ইনস্টল করতে চান সেখানে যান। এরপর কমান্ড দিন- ``` laravel new project_name ``` **কম্পোজার** কম্পোজার পিএইচপির প্যাকেজ ম্যানেজার। রুবির জন্য যেমন বান্ডলার, পাইথনের জন্য পাইপ, নোডের জন্য যেমন এনপিএম ঠিক তেমনি আমরা যারা পিএইচপিতে কাজ করি তাদের জন্য রয়েছে কম্পোজার। আপনি যদি `*nix` ব্যবহারকারী হয়ে থাকেন তাহলে খুব সহজেই কম্পোজার ইনস্টল করতে পারবেন। আপনি দুইভাবে কম্পোজার ইনস্টল করতে পারেন। একটি প্রজেক্ট ব্যাসিসে আর অন্যটি গ্লোবালি। আমি অবশ্য গ্লোবালি কম্পোজার ইনস্টল করাকেই পছন্দ করি। কম্পোজার ইনস্টল করতে চাইলে আপনার পিসিতে অবশ্যই পিএইচপি ইনস্টল থাকা লাগবে। এরপর আপনার পিসিতে যদি `cURL` ইনস্টল করা থাকে তাহলে নিচের কমান্ডরটি লিখুন- ``` curl -sS https://getcomposer.org/installer | php ``` আর যদি `cURL` ইনস্টল করা না থাকে তাহলে নিচের কমান্ডরটি লিখুন- ``` sudo apt-get install php5-curl ``` এই কমান্ডগুলি আপনার php.ini ফাইলের বেশ কিছু সেটিংস চেক করে তারপর ইনস্টল হবে। এতে কম্পোজার ইনস্টল হবে লোকালি। একে গ্লোবালি ইনস্টল করতে চাইলে আর্কাইভটিকে আপনার ক্লাস পাথ সেট করা আছে এমন জায়গায় মুভ করুন। মুভ করতে নিচের কমান্ডটি লিখুন- ``` (sudo) mv composer.phar /usr/local/bin/composer ``` আপনি যদি উইন্ডোজ ব্যবহারকারী হয়ে থাকেন তবে আপনি কম্পোজার [উইন্ডোজ ইনস্টলার](https://getcomposer.org/Composer-Setup.exe)টি নামিয়ে আপনার পিসিতে ইনস্টল করে নিন। এরপর যেখানে ফাইলটি ইনস্টল হয়েছে, সেখানকার পাথ আপনার মেশিনের পাথ ভ্যারিয়েবলে যুক্ত করুন। এরপরের কাজ খুবই সোজা। টার্মিনাল বা কমান্ডলাইন থেকে যেখানে লারাভেল ইনস্টল করতে চান, সে ফোল্ডারে নেভিগেট করুন। তারপর নিচের কমান্ডটি লিখুন- ``` composer create-project larval/laravel project_name –-prefer-dist ``` উপরের কমান্ডটি একটু ব্যাখ্যা করি। প্রথমে আমি লিখেছি `composer`. এটা দিয়ে আমি কম্পোজারকে ইনিশিয়ালাইজ করেছি। আমার পিসিতে কম্পোজার গ্লোবালি ইনস্টল করা আছে, যদি গ্লোবালি ইনস্টল করা না থাকতো তবে লিখতে হতো `php composer`. এরপর `create-project` এর মাধ্যমে নতুন প্রজেক্ট তৈরীর কথা বলেছি। এরপর `laravel/laravel` হলো প্রথমে প্রোভাইডারের নাম এবং পরে প্যাকেজের নাম। এরপর আপনি আপনার প্রজেক্টের নাম দিবেন, এটা না দিলে বাই ডিফল্ট লারাভেল নামের একটি ফোল্ডারে প্রজেক্টটি তৈরী হবে। আর সবশেষের `--prefer-dist` কথাটির মানে হচ্ছে সর্বশেষ স্টেবল রিলিজটি ইনস্টল করতে বলা। এটাও অপশনাল। এই কমান্ডটি দেয়ার পর আপনার পিসিতে লারাভেল ইনস্টল হবে। এটা আপনার ইন্টারনেট স্পিডের উপর ভিত্তি করে কয়েক সেকেন্ড থেকে শুরু করে কয়েক মিনিট লাগতে পারে। আর একটা কথা। আপনার পিসিতে লারাভেল ইনস্টল করতে হলে অবশ্যই পিএইচপির `mcrypt` এক্সটেনশন ইনস্টল থাকা লাগবে। আর যদি আপনি কম্পোজারের মাধ্যমে ইনস্টল করতে চান, তাহলে `php_openssl` একটিভেট করে নিতে হবে। আপনার পিসিতে ইতোমধ্যে লারাভেল ইনস্টল হয়ে গেছে। চেক করার জন্য টার্মিনালে লিখুন- ``` php artisan serve ``` এই কমান্ড আপনার পিএইচপির ডেভেলপমেন্ট সার্ভার `localhost:8000` পোর্টে চালু করবে। এবার আপনার ব্রাউজারে `localhost:8000` লিখলে দেখবেন লারাভেলের একটি বড় লোগো আর তার নিচে লেখা You have arrived. এই মাধ্যমে বুঝতে পারবেন আপনার পিসিতে লারাভেল ইনস্টল সফলভাবে সম্পন্ন হয়েছে। আমি চেষ্টা করেছি খুব সহজকরে, পুরো প্রক্রিয়াটিকে বর্ণনা করতে, যদি কোন বিষয় বাদ পড়ে থাকে বা আপনার পিসিতে লারাভেল ইনস্টল করতে কোন সমস্যা হয়, মন্তব্যে জানান। ধন্যবাদ। --- # গুগলের নতুন ফন্ট > My thoughts about google's new font. Published: 2014-07-17 URL: https://milon.im/post/googles-new-font.md গুগল গতকাল নতুন একটি ফন্ট রিলিজ দিয়েছে। গুগল এই ফন্ট ফ্যামিলির নাম দিয়েছে Noto. এর আগে এই ফন্টটি আমি প্রথম দেখি এন্ড্রয়েড ৪.৪ কিটক্যাটে। চমৎকার রেন্ডারিং করে। আমার এমনিতেই বাংলা ফন্টের উপর প্রচন্ড রকমের দূর্বলতা আছে। বাংলা ফন্টের সংখ্যা খুব বেশি না, তাই নতুন ফন্ট পেলেই ঈদ ঈদ লাগে। এই ফন্ট ফ্যামিলির বাংলা ফন্টটার রেন্ডারিং দূর্দান্ত। আমি এতটাই মুগ্ধ হয়েছি যে আমি আমার পিসির ডিফন্ট ফন্ট সোলাইমানলিপি থেকে চেঞ্জ করে নটোতে দিয়ে দিয়েছি। আপনারা ফন্টটির প্রভিউ পাবেন সাইটে। যদিও সম্পূর্ন ফন্ট ফ্যামিলির সাইজ প্রায় দেড়শ মেগাবাইট, তবে আপনি বাংলা ফন্টটা নামিয়ে নিতে পারবেন মাত্র ২০০ কিলোবাইট খরচ করেই। তবে ফন্টটার এখনো গুগলের ওয়েব ফন্ট সাইটে আসে নি। যদিও গুগল ফন্টের আর্লি একসেসে () ফন্টটা দেয়া আছে, তবে সেটা বেটা ভার্সন। আশা করি খুব শীঘ্রই ফন্টটার ফুল ওয়েবফন্ট রিলিজ দেবে গুগল। লাভ ফর গুগল এগেইন। --- # চিকিৎসাসেবায় নতুন দিগন্ত > mDoctor অ্যাপের মাধ্যমে ঘরে বসে বিশেষজ্ঞ চিকিৎসা সেবা — একটি নতুন দিগন্ত। Published: 2014-06-12 URL: https://milon.im/post/new-era-in-health-service.md ছোটবেলার একটা স্মৃতি শেয়ার করি। ডাক্তারের চেম্বারে গিয়েছি চোখ দেখাতে। সেখানে এক বৃদ্ধ চাচার সাথে দেখা। যিনি ঠাকুরগাঁ থেকে ঢাকা এসেছেন শুধুমাত্র ডাক্তার দেখাতে। চোখ দেখিয়েই তিনি আবার ঠাকুরগাঁয়ে ফিরে যাবেন। এটা তো অনেক আগের কথা। ইদানিং যারা বারডেম হাসপাতালে গিয়েছেন, তারা সবাই নিশ্চয়ই খেয়াল করেছেন, প্রতিদিন সকালে সারা দেশ থেকে কত শত মানুষ এখানে আসেন চিকিৎসা সেবা নিতে। আগের চেয়ে আমাদের দেশে ডাক্তারের সংখ্যা বেড়েছে, কিন্তু রোগীর সংখ্যা বেড়েছে বহুগুন বেশী। আর পরিসংখ্যান যাই বলুক না কেন, আপনি-আমি সবাই জানি বাংলাদেশের সিংহভাগ ডাক্তারই শহরে থাকেন। সুতরাং গ্রামে থাকা রোগীদের এখনো চিকিৎসা সেবা নিতে সাত-সমুদ্দুর তের নদী পারি নিয়ে শহরেই আসতে হয়। আর শহরের অবস্থাও যে খুব ভাল তাও নয়। ভীড়-যানযট পেরিয়ে বিশেষজ্ঞ ডাক্তারের চেম্বারে গিয়ে ঘন্টার পর ঘন্টা অপেক্ষা করতে হয়। আর এপয়েন্টমেন্ট নিতে হয় নিদেনপক্ষে সপ্তাহখানেক আগে, ক্ষেত্রবিশেষে এটা মাসখানেকও হতে পারে। TWGBD () বিভিন্ন বিষয়ের বিশেষজ্ঞ ডাক্তারদেরকে একটা প্লাটফরমে এনে দাড় করিয়েছে। আপনি এখন চাইলে ঘরে বসেই এন্ড্রয়েড মেবাইল ফোনের মাধ্যমে বিশেষজ্ঞ চিকিৎসা সেবা নিতে পারেন। এর জন্য আপনাকে গুগল প্লে স্টোর থেকে mDoctor () এ্যাপটি ডাউনলোড করে রেজিষ্ট্রেশন করতে হবে। এটার ব্যবহারবিধি খুবই সহজ, যে কোন স্মার্টফোন ব্যবহারকারী খুব সহজেই এটা ব্যবহার করতে পারবেন। চিকিৎসা সেবা নেয়ার জন্য ডাক্তারের ভিসিট দেয়া যাবে বিকাশের () মাধ্যমে। ভবিষ্যতে অন্যান্য পেমেন্ট মেথডও যোগ করা হবে। বর্তমানে এই এ্যাপটির সাহায্যে চর্ম ও যৌন রোগ (Dermatology & Venereology) এবং মেডিসিনের (General Medicine) চিকিৎসা দেয়া হচ্ছে। পর্যায়ক্রমে ডায়াবেটিস, কিডনি এবং মা-শিশুস্বাস্থ্যের চিকিৎসা সেবা দেয়া হবে। এ ব্যাপারে আরো বিস্তারিত জানার জন্য mDoctor এর ওয়েবসাইট ভিজিট করতে পারেন। এছাড়া নিয়মিত আপডেট পেতে mDoctor এর ফেসবুক পেজে () যোগ দিতে পারেন। এছাড়া জরুরী প্রয়োজনে যোগাযোগ করতে পারেন নিচের ঠিকানায়-
ফোন: ০১৭৯৫৫৭১৮৬৮
ইমেইল: mDoctorDB@gmail.com --- # সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৭ > My thoughts on Software Engineering's practical aspects. Published: 2012-12-12 URL: https://milon.im/post/software-engineering-practical-aspects-07.md একটা কথা খুব প্রচলিত টিমওয়ার্কের ক্ষেত্রে- > A 'jelled' team is a team functioning smoothly – like a well-oiled machine. কিন্তু স্টুডেন্ট প্রজেক্টের ক্ষেত্রে এটা বেশিরভাগ সময়ই কার্যকর হয় না। একটা টিম যখন কাজ করে তখন নানা ধরনের সমস্যা হওয়া খুবই স্বাভাবিক। কাজ করতে করতেই এই সমস্যাগুলোর সমাধান হয়ে যাবে। যখন কোন টিমমেট টিমে সমস্যা সৃষ্টি করে , ধরে নিতে হবে এটা সে ইচ্ছাকৃতভাবে করে নি। এছাড়া দলের সবাইকে তার ব্যাপারে সচেতন করে হবে। এবং তাকেও জানিয়ে দিতে হবে, তার আচরন দলে সমস্যার সৃষ্টি করছে। চুপ করে থাকা কখনোই সমস্যার সমাধান করবে না, বরং সমস্যা আরো বাড়িয়ে তুলবে। আসলে এ পর্বটা লেখা হচ্ছে সমস্যা সৃষ্টিকারী টিমমেম্বারদেরকে কিভাবে সামলাতে হয় তা নিয়ে। আসলে একটা টিমের সমস্যা কখনো শেষ হয় না, আর সমস্যার সাধারনত কোন ধরনও নেই। বেশিরভাগ টিমের সমস্যাই এড-হক সমস্যা। তবুও আমি কমন সমস্যাগুলোর কথা তুলে ধরার চেষ্টা করবো। **সমস্যা:** টিম মেম্বার যদি টিমের সবকিছুতে নাক গলায়, দলের নেতা হিসেবে জাহির হয়। সোজা বাংলায় আমরা যাকে বলি ভাব নেয়া। **সমাধান:** এটা আসলে মেনে নেয়া খুব কষ্টকর। প্রত্যেকটা সদস্যদকেই দলে দায়িত্ব পালন করতে হয়, কেউ যদি অন্যেক কাজের ক্রেডিট নিজে নিয়ে নেয়, তাহলে অন্যজন কাজ করার আগ্রহ হারিয়ে ফেলে। এ ধরনের সমস্যা দেখা দিলে টিম লিডারের উচিৎ সরাসরি তাকে জানানো। আর সে নিজেই যদি টিম লিডার হয়, তাহলে তাকে পরবর্তী মাইলস্টোনের সময় লিডারের দায়িত্ব থেকে অব্যাহতি দেয়া। **সমস্যা:** আরেকটা কমন সমস্যা হচ্ছে সাফারিং জিনিয়াস সিন্ড্রম। দলের অন্য সবার চেয়ে নিজেকে বেশি গুরুত্বপূর্ণ ভাবা এই সমস্যার সৃষ্টি করে। **সমাধান:** টিমওয়ার্ক একটা প্রজেক্টের জন্য খুবই গুরুত্বপূর্ণ। এ ধরনের সমস্যা যদি টিমের কারো মধ্যে থাকে তাহলে সেখানে কাজ করা খুবই সমস্যার। টিম লিডারের উচিৎ ঐ ব্যক্তিকে সরাসরি জানানো। এতে করে তার মোহভঙ্গ হবে। **সমস্যা:** টিমের মেম্বার অত্যন্ত ব্যস্ত। সে তার অন্যান্য কাজ নিয়ে খুব ব্যস্ত, তাই প্রজেক্টের কাজে সময় দিতে পারে না। **সমাধান:** সত্যিকারের সমস্যা একজনের থাকতেই পারে। সেক্ষেত্রে দলের সবার উচিৎ তাকে এ ব্যাপারে সাহায্য করা। তার সমস্যা যদি তার নিজের সৃষ্ট হয়, তাহলে তাকে এ ব্যাপারে সাবধান করে দেয়া দলনেতার দায়িত্ব। **সমস্যা:** টিমের মেম্বার অত্যন্ত ব্যস্ত। সে তার অন্যান্য কাজ নিয়ে খুব ব্যস্ত, তাই প্রজেক্টের কাজে সময় দিতে পারে না। পারসোনাল এফেয়ার প্রব্লেম একটা কমন সমস্যা। আত্মীয় মারা গেছে, টিম মেম্বার অসুস্থ, গার্লফ্রেন্ড বা বয়ফ্রেন্ডের সাথে মনোমালিন্য... এই ধরনের সমস্যা। **সমাধান:** সমস্যা মানুষের থাকবেই। সমস্যা পাশ কাটিয়েই কাজ করতে হবে। টিম মেম্বারকে মানসিক সাপোর্ট দেয়া, পাশাপাশি তাকে কাজে মনোনিবেশ করতে উদ্বুদ্ধ করার দায়িত্ব দলের সকলকেই নিতে হবে। **সমস্যা:** টিমের মেম্বার অত্যন্ত ব্যস্ত। সে তার অন্যান্য কাজ নিয়ে খুব ব্যস্ত, তাই প্রজেক্টের কাজে সময় দিতে পারে না। টিম লিডার নিজের কাজ নিয়েই পড়ে থাকে। টিম লিডারের দায়িত্ব পালন করে না। **সমাধান:** কিছু লোক নেতা হওয়ার জন্য আসে নি। তার উপর জোড় করে দলনেতার দায়িত্ব চাপিয়ে দেয়া উচিৎ না। এতে দলের যেমন ক্ষতি হয়, তেমনি তার ব্যক্তিগত পারফরমেন্সেও ব্যঘাত ঘটে। **সমস্যা:** টিমের মেম্বার অত্যন্ত ব্যস্ত। সে তার অন্যান্য কাজ নিয়ে খুব ব্যস্ত, তাই প্রজেক্টের কাজে সময় দিতে পারে না। টিম মেম্বার স্কীলড না, দূর্বল। সে তার কাজ ঠিকমত করতে পারছে না। **সমাধান:** একটা টিমে কখনোই সবাই একরকম হয় না। যে দূর্বল তাকে কঠিন কাজ দেয়া উচিৎ না। তার সামর্থ্যের মধ্যে কাজ দিতে হবে। এছাড়া দলের স্কীলড মেম্বারদের উচিৎ তাকে বিভিন্ন কাজে সাহায্য করা। এছাড়াও আরো কিছু সমস্যা থাকে যেমন- টিম মেম্বারের প্রজেক্টের প্রতি আগ্রহ নেই, টিম মিটিংয়ে সে কোন মন্তব্য করে না ইত্যাদি। আসলে এ ধরেনের সমস্যার কোন ধরাবাধা সমাধান নেই। দলের সবার সাথে আলোচনা করে এই সমস্যার সমাধান করতে হবে। --- # আবোল-তাবোল ২ > আবোল-তাবোল চিন্তা। Published: 2012-12-08 URL: https://milon.im/post/abol-tabol-2.md আজকে ঢাকা ফিরলাম প্রায় ১০ দিন পর। ৪টা বছর টাঙ্গাইল থাকার পর এখন আর টাঙ্গাইল সহ্যই হচ্ছে না। একটু ফুসরত পেলেই ঢাকা চলে আসতে ইচ্ছা করে। ঢাকা জ্যামের নগরী হোক, নোংরা হোক, ঢাকার হাজারটা দোষ থাকুক, তবুও ঢাকা এলেই মনটা ভাল হয়ে যায়। আজকে ঢাকা ফিরতে সময় লেগেছে ৬ ঘন্টার মত, যদিও দুই ঘন্টার রাস্তা। আশুলিয়ার দিকে প্রচন্ড জ্যাম ছিল। নিশ্চিন্তপুর এসে আগুনে পোড়া তাজরিন গার্মেন্টস চোখে পড়ল। মনটা বিষিয়ে উঠেছে এইসব অর্থলোভী নরপিশাচ গার্মেন্টস মালিকদের কাজকর্ম দেখে। স্যাররা নানা ধরনের পেইন দেয়া শুরু করেছে। আজকে বাহার ভাই সিমুলেশন পরীক্ষার গার্ড দিয়েছেন। আরে বাবা আপনিও তো বছর তিনেক আগে আমাদের জায়গায় ছিলেন। পরীক্ষায় ছেলে-পেলে একটু দেখাদেখি করবেই। তাই বলে এমন আচরন আপনার কাছ থেকে অন্তত আশা করি নি। গতকাল দিনটা খারাপ গেছে। সকালে পেনড্রাইভটা নষ্ট হয়ে গিয়েছিল। সন্ধ্যায় গেলাম দোকানে ওয়ারেন্টির জন্য, কিন্তু জামাতীদের ভয়ে দোকান-পাট কিছুই খোলে নি। বাসায় ফিরে দেখি ডেক্সটপ আর বুট হয় না। মহা যন্ত্রনা। বাধ্য হয়ে পিসি নতুন করে সেটআপ দিতে হল। বেশ কিছু ডাটা ডেক্সটপে ছিল, সব পগারপার। :'( বাংলাদেশ আজকে হারল বাজে খেলেছে বলে, ওয়েস্ট ইন্ডিজ ভাল খেলে জিতে নি। বাংলাদেশ যদি শুধুমাত্র একটু ভাল ফিল্ডিং দিত আর ক্যাচগুলো না মিস করতো, তাহলে এই কম স্কোরেও ওয়েস্ট ইন্ডিজকে আটকে ফেলা যেত। রুবেল এক ওভারে ২৪ রান দেয়ায় যারা ওর চৌদ্দ গোষ্ঠী উদ্ধার করছে তাদেরকে মনে করিয়ে দিতে চাই, এই রুবেলই কিন্তু নিউজিল্যান্ডের বিরুদ্ধে দুইটা ম্যাচে শেষ ওভার বল করে বাংলাদেশকে জয় এনে দিয়েছিল। আগামীকাল ডিজিটাল ওয়ার্ল্ড ২০১২ সম্মেলন শুরু হচ্ছে। ভাবতেই ভাল লাগছে। ঈদ ঈদ লাগছে। দেশে এই প্রথম এই সম্মেলনে ১০০ মেগাবাইট ব্যান্ডউইথ স্পিডের ইন্টারনেট পাওয়া যাবে। ইচ্ছা ল্যাপটপ নিয়ে গিয়ে নতুন লিনাক্স প্যাকেজগুলো সব আপডেট দিয়ে আনবো। ওডেস্ক, ফ্রিল্যান্সার, ইল্যান্স এ ধরনের বড় মার্কেট প্লেসগুলোর প্রায় সবকয়টির নজর এখন বাংলাদেশের উপর। দেশ যে প্রযুক্তি ক্ষেত্রে ভালই এগিয়ে যাচ্ছে তা চোখের সামনেই দেখতে পাচ্ছি। ভাল, ভাল। মুনীর হাসান স্যারের ভাষায় বলি, বাংলাদেশের সেকেন্ড ডিফারেন্সিয়াল নেগেটিভ হোক। --- # সাবাশ বাংলাদেশ!!! > বাংলাদেশ ক্রিকেট দলকে অভিনন্দন। Published: 2012-12-08 URL: https://milon.im/post/congratulation-bangladesh.md সাবাশ বাংলাদেশ!!! সাবাশ বাংলাদেশের ক্রিকেট!!! সাবাশ বাংলাদেশের মানুষ!!! বিজয়ের মাসে এর চেয়ে বড় প্রাপ্তি আর কি হতে পারে। টানা দুই ম্যাচ হারের পর বাংলাদেশ যে এভাবে ঘুরে দাড়াবে তা ভাবতেই পারি নি। বাংলাদেশের ক্রিকেট যে দিন দিন উন্নতি করছে তা চাক্ষুষ হচ্ছে। আমরা আগামী দুই বিশ্বকাপের মধ্যেই কাপটা ঘরে আনবো। ![Congratulation Bangladesh](/assets/images/posts/congratulation-bangladesh.jpg) আমাদের ছেলেরা করে দেখিয়েছে। ওয়েস্ট ইন্ডিজের মত দল যে দলের ১০ জন ব্যাটসম্যান, সে দলকে কিভাবে কম রানে বেধে ফেলা যায়, যে দল সবেমাত্র আইসিসি ওয়ার্ল্ড টি-২০'র কাপ ঘরে তুলেছে, তাদের কাছ থেকে কিভাবে কাপ ছিনিয়ে নিতে হয়। সাকিব দলে নেই বলে যে দুশ্চিন্তা হচ্ছিল সিরিজ শুরুর আগে, সেটা দূর করে দিয়েছে টাইগাররা। প্রমাণ করেছে, বাংলাদেশ দলের প্রত্যেকটি খেলোয়ার এক একটা সাকিব। যারা বাংলাদেশের ক্রিকেট নিয়ে কটুকথা বলেছে, বিশেষ করে গাধার বাচ্চা নভোজাত সিং সিধু আর বান্দর শেবাগ, তাদের মুছে চুন-কালি দিয়েছে টাইগাররা। সাবাশ টাইগারস! শেষ ওভারে ওয়েস্ট ইন্ডিজ যে নাটকটা করল সেটা না করলেও পারতো। ওরা রান নেয়নি ঠিক আছে, কিন্তু ওয়েস্ট ইন্ডিজের খেলোয়াররা স্ট্যাম্প তুলে কি প্রমান করতে চাইলো। শুধু বাংলাদেশের খেলোয়াররা বলে ম্যাচ শেষে ওদের সাথে হাত মিলিয়েছে। অন্য কোন টিমের খেলোয়াররা হলে সনে হয় না হাত মেলাত। ইলিয়াস সানির কান্ডটা দেখে ১৯৯৯ এর বিশ্বকাপে ল্যান্স ক্লুজনারের কথা বার বার মনে পড়ছে। কাজের কাজ আগে না করে আনন্দে লাফালাফি বেশি করলে পরিনতি হনে হয় এমনি হয়। তবে যে যাই বলুক না কেন, এই ঘটনার কারনে আমি ইলিয়াস সানির ফ্যান হয়ে গেলাম। বাংলাদেশের সিরিজ জেতার আনন্দ কিছুটা হলেও কম হতো, যদি সানি এই কাজটা না করতো। এই প্রথম একটা ম্যাচে না ভুল বললাম, একটা সিরিজে আগাগোড়া মাহমুদুল্লাহ রিয়াদকে ভাল খেলতে দেখলাম। আশা করি রিয়াদ ভবিষ্যতে আর কখনোই আমাদেরকে হতাশ করবে না। শেখ হাসিনাকে অভিনন্দন। দেশের প্রধানমন্ত্রী হয়ে তিনি বাংলাদেশ ম্যাচ জেতার সাথে সাথেই জাতীয় পতাকা নিয়ে যে শিশুসুলভ উচ্ছাস দেখিয়েছেন, তা দেখে আমি মুগ্ধ। দেশের প্রত্যেকটা মানুষের মধ্যে এমন অনুভূতি থাকা প্রয়োজন। এছাড়া জিল্লু চাচার ছেলে পাপনের সদা হাস্যোজ্বল মুখটাও বার বার মনে পড়ছে। আবার বলি, **সাবাশ বাংলাদেশ!!!** --- # সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৬ > My thoughts on Software Engineering's practical aspects. Published: 2012-12-04 URL: https://milon.im/post/software-engineering-practical-aspects-06.md **টিম লিডার** প্রত্যেকটা দলে একজন করে টিম লিডার থাকা প্রয়োজন যার তত্ত্বাবধানে পুরো টিম একসাথে কাজ করবে। স্টুডেন্ট প্রজেক্টগুলোতে নিয়ম-শৃঙ্খলা থাকে না। তাই এক্ষেত্রে টিম লিডার থাকা আরো বেশি জরুরী। টিম লিডার মানে এই নয় যে তার অবস্থান টিমের সবার চেয়ে উপরে বা সবার চেয়ে ভাল। টিমের অন্য একজন প্রজেক্টের জন্য যতটুকু গুরুত্বপূর্ণ, টিম লিডারও ততটুকু গুরুত্বপূর্ণ। সে শুধুমাত্র বাড়তি কিছু দায়িত্ব পালন করে নিজের কাজের পাশাপাশি। এটা পরীক্ষিত যে লিডারশিপ রোটেশন অর্থাৎ, যদি দলের সবাই কিছুদিন করে টিম লিডারের দায়িত্ব পালন করে তাহলে প্রজেক্টের আউটপুট ভাল হয়। এতে করে দলের সবাই কাজের প্রতি যত্নবান হয় এবং কাজের মধ্যে একটা প্রতিযোগীতার মনোভাব সৃষ্টি হয় যা একটা ভাল প্রজেক্টের জন্য অত্যন্ত গুরুত্বপূর্ণ। আর একটা গুরুত্বপূর্ণ বিষয় হচ্ছে যে কোন সিদ্ধান্ত নেবার টিম লিডারকে দলের সবার সাথে আলোচনা করে সিদ্ধান্ত নেয়া উচিৎ। এতে ভুলের সম্ভাবনা অনেক কম থাকে। একজনের মাথা থেকে যে বুদ্ধি আসে পাঁচজন বা দশজনের মাথা থেকে অবশ্যই আরো ভাল বুদ্ধি আসবে। **টিমে মানিয়ে চলা** এবার আলোচনা করবো একটা দলে কাজ করতে গেলে সাধারনত কি কি ঝামেলার সম্মুখীন হতে হয় তা নিয়ে। **সমস্যা:** দলের সবাই আপনার মতের বিরুদ্ধে সিদ্ধান্ত নিয়েছে। **পরামর্শ:** যদি তোমার ডিসিশন দলের সবার সাথে নাও মিলে যায় তবে এটা ভাল কোন আউটকাম এনে দিতেও পারে। একটা কথা আমি বিশ্বাস করি, ম্যাক্সিমাম এজ অলওয়েজ রাইট। আসলে দলের সবাই মিলে যখন কোন গুরুত্বপূর্ণ সিদ্ধান্ত নেয়, সেটা অবশ্যই অনেক ভেবে চিন্তে নেয় এবং দলের ভাল'র জন্যই নেয়। যদিও সব সিদ্ধান্ত সব সময় সঠিক হয় না, তবুও দলের সিদ্ধান্তের প্রতি শ্রদ্ধাশীল হতে হবে। **সমস্যা:** দলের অন্যান্য সদস্য পূর্বপরিচিত, নিজেকে আউটসাইডার মনে হওয়া। কোন গুরুত্বপূর্ণ দায়িত্ব না পাওয়া। **পরামর্শ:** এই সমস্যার প্রথম সমাধান হচ্ছে রেইজ ইউর ভয়েজ। আপনি দলের সবাইকে বলুন এর চেয়ে বেশী আপনি করতে পারেন। যদি এতে কাজ না হয় তাহলে আপনার টিমলিডার বা সুপারভাইজারকে জানান। আর এই সমস্যা দেখা দেয়ার সাথে সাথেই পদক্ষেপ নেয়া উচিৎ। দেরী করলে সমস্যা আরো বাড়ে। **সমস্যা:** আপনার টিম আপনাকে ছাড়াই কাজ ভালভাবে শেষ করছে। আপনার কাজের সঠিক মূল্যায়ন পাচ্ছেন না। **পরামর্শ:** আপনি আপনার উপর অর্পিত দায়িত্ব সঠিকভাবে পালন করুন এবং কেউ যদি আপনাকে দেয়া কাজ নিজে করে ফেলে তাকে সরাসরি জানান। সমঝোতার মাধ্যমে এই সমস্যা সমাধান করা উচিৎ। আর আপনার কাজের মান যদি ভাল না হয়ে থাকে, তাহলে তাদের সাহায্য নিয়ে নিজের কাজের মানের উন্নতি করার চেষ্টা করুন। **সমস্যা:** আপনি আপনার উপর অর্পিত দায়িত্ব সঠিকভাবে পালন করতে পারেন নি। আপনি আপনার দলের অন্যদের মত স্কিলধারী নন। পরামর্শ: কোন টিমই পারফেক্ট না। প্রত্যেকটা টিমেই কমবেশি সমস্যা থাকে। আপনি হয়তো প্রোগ্রামিংএ দূর্বল কিন্তু অন্য দিক যেমন ডেটাবেজ ডিজাইনে আপনার ভাল দক্ষতা রয়েছে। তাহলে আপনি আপনার টিম লিডারকে অবহিত করুন যাতে আপনার উপর এ ধরনের দায়িত্বই অর্পিত হয়। এছাড়া নিজের স্কিল বাড়ানোর জন্য দলের অন্যান্য সদস্যদের সাহায্য নিন এবং নিয়মিত এ সংক্রান্ত বিভিন্ন বই পড়ুন। আমি নিজে বিশ্বাস করি, যে কোন কিছু শেয়ার সবচেয়ে ভাল মাধ্যম হচ্ছে বই। --- # সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৫ > My thoughts on Software Engineering's practical aspects. Published: 2012-11-29 URL: https://milon.im/post/software-engineering-practical-aspects-05.md > তুমি কখনোই একটা ভাল টিম ছাড়া একটা ভাল সফটয়্যার তৈরী করতে পারবে না এবং দূর্ভাগ্যজনক হলেও সত্য হচ্ছে প্রত্যেকটা টিমই অবুঝ প্রেমিকার মত আচরন করে। -- জন ম্যাকার্থি **দলে কাজ করতে শেখা** স্টুডেন্ট প্রজেক্টগুলোতে সাধারনত একটা টিমের বৈশিষ্ট্য থাকে- - আপনার টিমের এক/দুইজন দক্ষ এবং বাকিরা নবীশ থাকে, আপনারা যে ক্ষেত্রে কাজ করতে চান সেখানকার ব্যাপারে। - টিমের সাইজ ফিক্সড থাকে এবং এটা সাধারনত খুব বড় হয় না। - আপনি প্রজেক্ট চলাকারীন সময়ে টিমমেম্বার বাড়াতে বা ছাটাই করতে পারবেন না। - আপনি বাইরের কাইকে দিয়ে কাজ করিয়ে নিতে(আউটসোর্সিং) পারবেন না। **টিমিং আপ** আপনার উপর যদি দায়িত্ব থাকে টিম মেম্বার বাছাই করা তাহলে এটাকে গুরুত্ব সহকারে নিন। চেষ্টা করুন সেরা টিমটা নির্বাচন করতে। আর আপনাকে যদি কেউ টিমমেট হতে আহবান জানায় তাহলে তার পূর্বের প্রজেক্টটি দেখুন, সে কি করেছে? এছাড়া তার ব্যক্তিগত অন্যান্য কাজকর্মগুলোও লক্ষ্য করুন। আসলে যদি টিমমেটদের ওয়ার্কিং শিডিউল একই ধরনের হয় তাহলে কাজ করতে সুবিধা হয়। টিমের প্রত্যেক সদস্যের জীবন-যাপন স্টাইল এক রকম হলে সে টিম থেকে সর্বোত্তম আউটপুট পাওয়া সম্ভব। যেমন টিমের একজন সদস্য খুব সকালে ঘুম থেকে ওঠে আবার তাড়াতাড়ি ঘুমিয়ে পড়ে এবং অন্য একজন সদস্য দেরি করে ঘুম থেকে ওঠে এবং রাত জেগে কাজ করে। তাহলে এদের ওর্য়াকিং শিডিউল এক করা সম্ভব হবে না এবং টিমের কাছ থেকে ভাল ফলাফলও পাওয়া যাবে না। এছাড়া টিমের প্রত্যেক সদস্যের এক্সপেক্টেশন লেভেল এক হওয়া উচিৎ। টিম তৈরী করার সময় টিমটা যাতে ব্যালান্স হয় সেদিকে লক্ষ্য রাথতে হবে। টিমের সবাই যদি শুধুমাত্র একটি বিষয়েই পারদর্শী হয় তাহলে কাজের আউটপুট ভাল হবে না। তাই টিম তৈরী করার সময়, ডিজাইনার, গ্রাফিক্যাল ইউজার ইন্টারফেস(GUI) এক্সপার্ট, প্রোগ্রামার, ডেটাবেজ এক্সপার্টদের সমন্বয়ে টিম তৈরী করা উচিৎ। টিমে যদি আপনার ঘনিষ্ট বন্ধুরা থাকে তাহলে আপনি অনেক সুবিধা পাবেন, তবে এর অসুবিধাও আছে। আপনি এক্ষেত্রে কাজ করার সময় প্রফেশনাল এটমোস্ফিয়ার ধরে রাখতে পারবেন না। এছাড়া কোন সদস্য ঠিকমত কাজ করতে না পারলেও আপনি বন্ধুত্বের খাতিরে কিছু বলতেও পারবেন না। তবে এ সমস্যা কিভাবে সমাধান হবে তার উত্তর আমার জানা নেই। একটা টেমর বিভিন্ন দিকে কাজ করতে হয়, এমনকি যেদিকে কোন সদস্যেরই দক্ষতা নেই সেদিকেও। এক্ষেত্রে প্রত্যেকটা অংশ ভাগ ভাগ করে একজন করে সদস্যকে সে অংশের দায়িত্ব দিয়ে দেয়া উচিৎ। তার কাজ হবে সে অংশ সম্পর্কে যথাযত ধারনা অর্জন করা এবং টিমের অন্যান্য সদস্যদেরকে তা জানানো। উদাহরনসরূপ, যে টেস্টিংয়ের দায়িত্বে থাকবে তার দায়িত্ব হচ্ছে বিভিন্ন টেস্টিং টুল সম্পর্কে জানা, টেস্টিং পলিসি কি হবে সেটা নির্ধারন করা, টেস্ট প্ল্যান নির্ধারন করা, টেস্টিংয়ের সময় কিভাবে ট্রাবলশুটিং করা হবে সেটা জানা এবং সদস্যদেরকে সেটা জানানো। টিমের প্রত্যেক সদস্যদের কেমন হওয়া উচিৎ তা নিয়ে একটা কথা খুব প্রচলিত আছে, > Jack of all trades and a master of at least one. অর্থাৎ প্রত্যেক সদস্যের সব বিষয়েই একটা মোটামুটি ধারনা থাকতে হবে এবং কমপক্ষে একটা ক্ষেত্রে ভাল দক্ষতা থাকতে হবে। আরেকটা জিনিসের দিকে লক্ষ্য রাখা উচিৎ। একটা স্টুডেন্ট প্রজেক্টের প্রায় সকলেই নবীশ থাকে। এক্ষেত্রে কোন একটা সেক্টেরের মাস্টার হতে হলে তার পেছনে যথেষ্ট সময় ব্যয় করতে হবে। আর আপনার পছন্দের ক্ষেত্রটিই যদি আপনি মাস্টার হবার জন্য নির্বাচন করেন, তাহলে সে ক্ষেত্রে কাজটা আরো সহজ হয়ে যায়। --- # সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৪ > My thoughts on Software Engineering's practical aspects. Published: 2012-11-28 URL: https://milon.im/post/software-engineering-practical-aspects-04.md **প্রজেক্ট ঝুঁকি** এই পর্বে আমরা দেখবো একটা প্রজেক্ট করতে গেলে সাধারনত কি কি ঝুঁকিতে পড়তে হয় এবং সমস্যা সমাধানের জন্য আমাদের কি কি করতে হবে। প্রজেক্ট চলাকালে যে কোন সমস্যা দ্রুত ধরতে পারা এবং তা সমাধানের জন্য দ্রুত ব্যবস্থা নেয়া অত্যন্ত গুরুত্বপূর্ণ। **ঝুঁকি:** আপনি হয়তো প্রজেক্ট রিকোয়ারমেন্ট ভালভাবে বুঝতে পারেন নি এবং ভুল প্রোডাক্ট তৈরী করে সময় নষ্ট করছেন। **সমাধান:** দ্রুত এবং নিয়মিত বিরতিতে প্রজেক্ট তদারক করা খুবই গুরুত্বপূর্ণ। প্রথমেই উচিৎ ক্লায়েন্টের/সুপারভাইজারের কাছ থেকে প্রজেক্ট রিকোয়ারমেন্ট ভালভাবে বুঝে নেয়া এবং টিমের প্রত্যেক সদস্যকে এর একটি করে কপি দেয়া। এক্ষেত্রে ইউএমএল ডায়াগ্রাম ব্যবহার করলে সবচেয়ে ভাল ফল পাওয়া যায়। টিমের কোন সদস্য কোন কাজ করবে তা প্রথমেই নিশ্চিত করে নেয়া উচিৎ। কোন ধরনের ধরনের দ্বিমত থাকলে সুপারভাইজারের সাথে কথা বলে দ্বিধা দূর করে নেয়া উচিৎ। আর প্রজেক্ট যদি সরাসরি আপনার তত্ত্বাবধানে পরিচালিত হয় তাহলে টিমের প্রত্যেক সদস্যকে প্রজেক্টের খুটিনাটি বুঝিয়ে দেয়া আপনার দায়িত্ব। **ঝুঁকি:** কোন কোন গ্রুপ মেম্বার হয়তো আশানুরূপ কাজের আউটপুট দিতে পারছে না বা প্রজেক্টে কাজ করা অন্যান্য সদস্যদের সাথে ভাল ব্যবহার করছে না। **সমাধান:** এ ব্যাপারে শুরুতেই ব্যবস্থা নেয়া উচিৎ এবং অভিযুক্ত সদস্যকে জানিয়ে দেয়া উচিৎ যে তার ব্যবহার ঠিক হচ্ছে না। প্রত্যেককে শুধুমাত্র তাদের উপর অর্পিত দায়িত্বই পালন করার কথা মনে করিয়ে দেয়া উচিৎ। সবচেয়ে ভাল হয় গুগলডক্সে একটা স্পেডশিট তৈরী করা সেখানে সবার দায়িত্ব দিয়ে দেয়া এবং সেটা নিয়মিত মূল্যায়ন করা। সবার সাথে স্পেডশিটটি শেয়ার করলেও ভাল হয়। তবে মূল্যায়ন সবার সাথে শেয়ার করা উচিৎ না। **ঝুঁকি:** কিছু সদস্যের হয়তো প্রজেক্টে কাজ করার জন্য প্রয়োজনীয় দক্ষতা নেই। বিশেষ করে স্টুডেন্ট প্রজেক্টগুলো করার ক্ষেত্রে এই সমস্যায় প্রায়সই পড়তে হয়। **সমাধান:** যদিও এক্সটার্নাল রিসোর্স যেমন- বই, টিউটোরিয়াল ইত্যাদি স্কীল তৈরীতে খুব সাহায্য করে তবে ব্যবহারিক কাজ করার ক্ষেত্রে গ্রুপে কাজ করলে এক্ষেত্রে আরো বেশি সুবিধা পাওয়া যায়। টিমের দক্ষ সদস্যদের উচিৎ নবীশদের সাহায্য করা। এক্ষেত্রে পেয়ার প্রোগ্রামিং মেথড ব্যবহার করলে খুব ভাল ফল পাওয়া যায়। **ঝুঁকি:** প্রজেক্টের সম্পূর্ণ টিমকে যদি আলাদা আলাদা সাব-গ্রুপে ভাগ করে কাজ করা যায় তবে অনেক ভাল ফলাফল পাওয়া যায়। তবে অনেক সময়ই একটি সাব-গ্রুপ কাজ খারাপ করলে পুরো প্রজেক্টে এর খারাপ প্রভাব পড়ে। **সমাধান:** সাব-গ্রুপ তৈরী করার সময় স্কীল, কমিটমেন্ট এ সূচকগুলোর দিকে খেয়াল রেখে ব্যালেন্স দল তৈরী করা উচিৎ। এছাড়া ক্রস টেস্টিং(এক গ্রুপের কাজ অন্য গ্রুপের দ্বারা মূল্যায়ন) এক্ষেত্রে খুব ভাল কাজ করে এবং সাব-গ্রুপগুলোর মধ্যে একটা প্রতিযোগীতার মনোভাব তৈরী করে। **ঝুঁকি:** স্টুডেন্ট প্রজেক্টগুলোর ক্ষেত্রে একটা কমন সমস্যা হচ্ছে এর নির্দিষ্ট ডেডলাইনের মধ্যে কাজ শেষ করতে না পারা। **সমাধান:** প্রথম থেকে সাবধান থাকলে ডেডলাইন ওভারশুটিং এড়ানো যায়। একটা ভাল পদ্ধতি হচ্ছে পুরো প্রজেক্টকে ছোট ছোট অংশে ভাগ করে প্রত্যেকটার জন্য আলাদা আলাদা ডেডলাইন তৈরী করে কাজ করা। **ঝুঁকি:** প্রজেক্ট করার সময় অনেকসময়ই নানা আনএক্সপেক্টেড ডিলে হয়ে যায়, যেমন কোন সদস্য হঠাৎ করে অসুস্থ হয়ে যাওয়া, কোন সদস্য টিম হতে বেরিয়ে যাওয়া ইত্যাদি। **সমাধান:** কখনোই কোন একজন সদস্যদের উপর অনেক বেশি নির্ভরশীল হওয়া উচিৎ না। এছাড়া বাফার টাইমিং ব্যবহার করা উচিৎ অর্থাৎ, প্রজেক্টের প্রত্যেকটা অংশের কাজ শেষ করতে যে সময় লাগবে তার চেয়ে কিছুটা বেশি সময় হাতে রাখা। **ঝুঁকি:** অনেক সময়ই যে সময়ে কাজ শেষ করা যাবে বলে ধারনা করা হয়েছিল, ইচ্ছা সত্ত্বেও সে সময়ে কাজ শেষ করা যায় না। **সমাধান:** প্রজেক্টের অপরিচিত(Unfamiliar) অংশগুলোর কাজ প্রথমেই করা উচিৎ। কঠিন অংশের কাজ শুরুতেই করে ফেলা উচিৎ। বলা হয়ে থাকে যদি অনেক খাবার একসঙ্গে খেতে হয় তাহলে বিদঘুটে খাবারগুলোই প্রথমে খেয়ে নেয়া উচিৎ। এছাড়া একই ধরনের কাজগুলো একসঙ্গে করলে সময়ের সাশ্রয় হয়। --- # সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-৩ > My thoughts on Software Engineering's practical aspects. Published: 2012-11-27 URL: https://milon.im/post/software-engineering-practical-aspects-03.md **প্রোডাক্ট রিলিজ** এ পর্বটি প্রোডাক্ট রিলিজ নিয়ে লেখা হবে। প্রোডাক্ট রিলিজ করার অনেকগুলো মাধ্যম রয়েছে। প্রথমে সিদ্ধান্ত নিতে হবে কিভাবে প্রোডাক্ট রিলিজ করা হবে সে সিদ্ধান্ত নেয়া। প্রোডাক্ট রিলিজের মধ্যে সবচেয়ে জনপ্রিয় মাধ্যমটি হচ্ছে পাবলিকলি রিলিজ করা। **পাবলিক রিলিজ** পাবলিক রিলিজের সবচেয়ে বড় সুবিধা হচ্ছে এর মাধ্যমে আপনি অনেক বেশি ইউজারের কাছে আপনার প্রোডাক্টটি পৌছে দিতে পারবেন। এক্ষেত্রে সবচেয়ে গুরুত্বপূর্ণ বিষয়টি হচ্ছে চেষ্টা করতে হবে যত বেশি সম্ভব পটেনশিয়াল ইউজারের কাছে প্রোডাক্টটি পৌছে দেয়া। অনেকগুলো সাইট আছে যেমন- [softpedia.com](http://www.softpedia.com), [cnet.com](http://www.cnet.com), [softsea.com](http://www.softsea.com), [Devhost](http://d-h.st) যারা তাদের সাইটে আপনাদের প্রোডাক্ট ফ্রিতে আপলোড করার সুযোগ দেবে যাতে আপনার প্রোডাক্টের ইউজার তা ডাউনলোড করতে পারে, আপনার সফটয়্যারকে রেটিং দিতে পারে, এমনকি তাদের রিভিউও প্রকাশ করতে পারে। এ ধরনের সাইটগুলোতে আপনার সফটয়্যার হোস্টিংয়ের সবচেয়ে বড় সুবিধা হলো আপনার সফটয়্যার যদি বেশি পরিমান ডাউনলোড হয় তাহলে [lifehacker.com](http://lifehacker.com), [addictivetips.com](http://www.addictivetips.com) এ ধরনের সাইটগুলো আপনার সফটয়্যারের রিভিউ ছাপানো শুরু করবে যা আপনার সফটয়্যারের প্রচারের জন্য সবচেয়ে ভাল। সবচেয়ে ভাল হয় যদি আপনার সফটয়্যারের নিজস্ব একটা সাইট থাকে এবং সেটা থাকে নিজস্ব ডোমেইনে। তবে সাধারনত প্রফেশনাল সফটয়্যারের ক্ষেত্রে এমনটা বেশি দেখা যায়। যেমন- [টালি](http://www.tallysolutions.com) আমাদের দেশের অত্যন্ত জনপ্রিয় একটি একাউন্টিং সফটয়্যার। এটার নিজ নামে ডোমেইন আছে। এছাড়া অনেক ফ্রি সাইটও আছে যেখানে আপনি আপনার সফটয়্যারের জন্য নিজস্ব সাইট বিনামূল্যে তৈরী করতে পারবেন। এর মধ্যে উল্লেখযোগ্য হচ্ছে গুগল সাইটস, ওয়ার্ডপ্রেস ইত্যাদি। যেমন- এন্ড্রয়েড মোবাইলের জনপ্রিয় কীবোর্ড [মায়াবী](http://mayabisoft.wordpress.com) তাদের প্রোডাক্ট ওয়ার্ডপ্রেসে হোস্টিং করেছে। এছাড়া ডেডিকেটেড প্রোজেক্ট হোস্টিং এনভায়রনমেন্টও ফ্রি পাওয়া যায় যেমন [গুগল কোড প্রজেক্ট হোস্টিং(GCPH)](http://code.google.com/hosting). এই সাইটেও আপনি আপনার প্রোডাক্টের জন্য ফ্রি ওয়েবসাইট খুলতে পারবেন। এছাড়াও আরো কয়েকটি উপায় রয়েছে প্রোডাক্টকে পাবলিকলি ইউজারের কাছে পৌছে দেয়ার। যেমন- - ফেসবুকে একটি ফ্যানপেজ তৈরী করা। - ইমেইল সিগনেচারে সফটয়্যারের লিঙ্ক দেয়া। - বিভিন্ন ফোরামে সফটয়্যারের রিভিউ পোস্ট করা। **রিলিজ পিরিওড** কখনোই সফটয়্যারটি এর পটেনশিয়াল ইউজারদের সাথে একবারে তুলে দেয়া উচিৎ না। আস্তে আস্তে রিলিজ দিলে সফটয়্যারটির বিভিন্ন বিষয় পরিবর্তন করে সফটয়্যারটি মার্কেটের জন্য আরো বেশি উপযুক্ত হিসেবে তৈরী হবে। যেমন জনপ্রিয় বাংলা টাইপিং সফটয়্যার [অভ্র](http://www.omicronlab.com/avro-keyboard.html)র কথাই ধরা যাক। এর ডেভেলপার মেহদী হাসান খান এর প্রত্যেকটা ভার্সনের প্রথমে এর একটা করে আলফা রিলিজ ছাড়েন যা তিনি তার বন্ধু-বান্ধবের মধ্যে ব্যবহার করতে দেন। এখান থেকে বিভিন্ন বাগ ঠিক করে এরপর তিনি ছাড়েন এর প্রাইভেট বেটা, যা তিনি তার পরিচিত গন্ডির মধ্যে ব্যবহার করতে দেন। এখান থেকে ফিডব্যাক নিয়ে তিনি রিলিজ দেন পাবলিক বেটা, যা [ওমিক্রনল্যাবের](http://omicronlab.com) ওয়েবসাইটে ডাউনলোডের জন্য রাখা হয়। এখান থেকে বিভিন্ন বাগ ঠিক করার মাধ্যমে রিলিজ দেয়া হয় এর ফাইনাল ভার্সন। এবার এভাবে রিলিজ দেয়ার আরেকটা অন্যতম কারন হচ্ছে আপনার সফটয়্যার আপনি যত ভাল করেই তৈরী করুন না কেন, আপনার কোর্স টিচার বা সুপারভাইজার এর মধ্যে কাটা-ছেঁড়া করবেনই। তাই গ্রাজুয়ালি রিলিজ করলে অনেক বেশি সুবিধা পাওয়া যায়। এটা ব্যক্তিগত অভিজ্ঞতা থেকে লিখলাম। **মেইনটেইনেন্স** একটা সফটয়্যার তৈরী করে রেখে দিলে এর উপোযোগীতা একসময় ব্যবহারকারীর কাছে আর থাকে না। তাই নিয়মিত নতুন নতুন আপডেট আর বিভিন্ন নতুন ফিচার সফটয়্যারে আনতে হবে। তা না হলে সফটয়্যার এর আবেদন আর ধরে রাখতে পারবে না। --- # সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-২ > My thoughts on Software Engineering's practical aspects. Published: 2012-11-26 URL: https://milon.im/post/software-engineering-practical-aspects-02.md কিছু কোর্স প্রজেক্ট আমাদেরকে বিভিন্ন ধরনের বাধ্যবাধকতা জুড়ে দেয়। যেমন- সি প্রজেক্ট করতে হয় বেশিরভাগ বিশ্ববিদ্যালয়গুলোতে। এছাড়া রয়েছে অবজেক্ট অরিয়েন্টেড প্রোগ্রামিংয়ের প্রজেক্ট যা সাধারনত সবাই জাভা বা সি# ব্যবহার করে করে। অন্যান্য ক্ষেত্রে ছাত্রদের স্বাধীনতা থাকে প্রজেক্ট করার ক্ষেত্রে। এছাড়া আমরা যখন ব্যবহারিক সফটয়্যার তৈরী করবো, তখনো ক্লায়েন্টের কাছ থেকে বিভিন্ন ধরনের চাহিদা বা রিকোয়্যারমেন্ট আসতে পারে। এ ব্যাপারগুলোর দিকে সব সময় খেয়াল রাখতে হবে। **প্রজেক্ট প্রস্তাবনা** প্রজেক্ট প্রস্তাবনা রাখার ক্ষেত্রে কয়েকটি বিষয় খেয়াল রাখা উচিৎ- - এমন বিষয় নির্বাচন করা উচিৎ যেটা নির্দিষ্ট সময়ের মধ্যে দলটি দ্বারা করা সম্ভব হবে। বেশিরভাগ প্রজেক্ট করার জন্য সময় থাকে ছয় মাস বা ক্ষেত্রবিশেষে এক বছর। এমন প্রজেক্ট কখনোই নির্বাচন করা উচিৎ হবে না, যা এই সময়ের মধ্যে করা সম্ভব হবে না। - প্রজেক্ট নির্বাচনের সময় কোন একজনের সমস্যার সমাধানের চেয়ে বেশি খেয়াল রাখা দরকার এটার ব্যবহারিক প্রয়োগের দিকে। একটা সফটয়্যার প্রজেক্টের টার্গেট পিপল বা ভোক্তা কারা হবে সে বিষয়ে খেয়াল রেখে প্রজেক্ট নির্বাচন করা উচিৎ। - যে সফটয়্যার বাজারে ইতোমধ্যে আছে সে ধরনের প্রজেক্ট নির্বাচন করা উচিৎ হবে না। আর নির্বাচন করা হলে অবশ্যই নতুন কোন বৈশিষ্ট্য যুক্ত করতে হবে যা বাজারে বিদ্যমান সফটয়্যারটিতে নেই। - একটা প্রজেক্ট নির্বাচন করার পর সেটিতে আস্থা রাখতে হবে। প্রায়সই দেখা যায় একটা প্রজেক্ট নির্বাচন করার কিছুপর সেটা বদলে অন্য প্রজেক্ট নেয়া হয়। এতে করে সময়ের অপব্যবহার হয় এবং আত্নবিশ্বাসে ফাটল ধরে। - সত্যিকারের ব্যবহারকারীদের টার্গেট করে সফটয়্যার তৈরী করতে হবে। অনেক সময় দেখা যায়, লাইব্রেরী ম্যানেজমেন্ট সিস্টেম, স্কুল ম্যানেজমেন্ট সিস্টেম বা এই ধরনের প্রজেক্ট নির্বাচন করা হয়, যা হয়তো কখনোই ব্যবহারিক কাজে ব্যবহৃত হবে না। এ ধরনের প্রজেক্ট নির্বাচন করলে যাতে ব্যবহারিক কাজে লাগানো যায় সেদিকে খেয়াল রাখতে হবে। - প্রজেক্টের একটি সুন্দর এবং অর্থপূর্ণ নাম রাখতে হবে। **প্রজেক্ট ফিচার** প্রজেক্টের ফিচার কি কি হবে সে দিকে সতর্ক দৃষ্টি রাখতে হবে। কোন কোন ফিচারের দিকে খেয়াল রাখলে প্রজেক্টটি অন্যান্য প্রোডাক্টের চেয়ে ভাল হবে সেদিকে হাইলাইট করতে হবে। প্রজেক্টের শুরুতেই প্রোডাক্টের ইউজার ইন্টারফেস কি হবে সেদিকে খেয়াল রাখতে হবে। প্রোডাক্টটি যাতে এর ইউজারের কাছে আকর্ষনীয় হয়, সেদিকে সর্বোচ্চ গুরুত্ব দিতে হবে। **প্রজেক্ট ফিডব্যাক** প্রজেক্ট চলাকালীন সময়ে প্রজেক্ট সুপারভাইজার বা ক্লায়েন্ট(বানিজ্যিক সফটয়্যারের ক্ষেত্রে) এর মতামত নিতে হবে। এ ক্ষেত্রে আমি সর্বদা মডেল-ভিউ-কন্ট্রোলার মডেল অনুসরনের পরামর্শ দেব। প্রত্যেকটা অংশ সম্পূর্ণ হওয়ার সাথে সাথে সুপারভাইজারের পরামর্শ নিতে হবে। তা না হলে প্রজেক্ট কমপ্লিট করার পর এমন কোন ফরমায়েশ আসতে পারে যার কারনে হয়তো পুরো প্রজেক্টটিকে নতুন করে ঢেলে সাজানোর দরকার পড়বে। সেটা একঘেয়েমীপূর্ণ আর বিরক্তিকর হবে। --- # সফটয়্যার ইঞ্জিনিয়ারিং: ব্যবহারিক আঙ্গিক-১ > My thoughts on Software Engineering's practical aspects. Published: 2012-11-25 URL: https://milon.im/post/software-engineering-practical-aspects-01.md **শুরুর আগে** আমি কোন প্রফেশনাল সফটয়্যার কোম্পানীতে কখনো কাজ করি নি। যদিও কয়েকটা সফটয়্যার তৈরীতে কাজ করেছি, যেগুলি প্রফেশনালি ব্যবহৃত হচ্ছে, তবে এর প্রায় কোনটাতেই নিয়ম মেনে কাজ করা হয নি। তবে অসাধারন কয়েকজন সফটয়্যার ডেভেলপারের সাথে আমার ব্যক্তিগত হৃদ্বতা আছে, তাদের কাছ থেকে অনেক কিছু শিখেছি। এ সিরিজটাতে আমি যা লিখবো তার প্রায় পুরোটাই আমার পুথিগত বিদ্যা আর কমন সেন্সের মিশেল। বাকিটা আমার ব্যবহারিক জ্ঞান। তাই এ লেখাতে কিছুটা ভুল-ভ্রান্তি থাকাটা অস্বাভাবিক নয়। খুব সিরিয়াসলি নেয়ার কোন দরকার নেই। **ভূমিকা** আমার এ লেখাটা ইঞ্জিনিয়ারিংয়ের ছাত্রদের উদ্দেশ্যে লেখা, যারা তাদের কোর্স কারিকুলামে সফটয়্যার ইঞ্জিনিয়ারিং বিষয়টা পড়ে। বাংলাদেশের বেশিরভাগ বিশ্ববিদ্যালয়ে সিএসসি, আইসিটি, সিএসটি প্রভৃতি সাবজেক্টে তিন বা তার চেয়ে বেশি ক্রেডিটের সফটয়্যার ইঞ্জিনিয়ারিং কোর্স পড়ানো হয়। তবে ব্যক্তিগত অভিজ্ঞতা থেকে জানি, মোট ছাত্রদের প্রায় ৯০ শতাংশেরই ছাত্রবস্থায় কোন প্রফেশনাল কাজের অভিজ্ঞতা থাকে না। এছাড়া বিভিন্ন প্রজেক্টে কাজ করার সময় দেখায় যায় গ্রুপের সাধারনত ১/২ জন কাজ করে, বাকিরা করে না। আমার এ লেখার উদ্দেশ্য সফটয়্যার তৈরী করা শেখানো না, বরং বিভিন্ন প্রজেক্টে কাজ করার সময় কিভাবে কাজ করতে হবে সেটা শেখানো। এছাড়া এ লেখাটা ব্যবহারিক সফটয়্যার তৈরীর ক্ষেত্রেও কাজে লাগবে বলে আমার বিশ্বাস। **সিদ্ধান্ত গ্রহণ** প্রথমেই কোন প্রজেক্টে কাজ করার জন্য সিদ্ধান্ত গ্রহণ করতে হবে। কোন প্রজেক্টে কাজ করবো, আমাদের তৈরী সফটয়্যারের কি কি বৈশিষ্ট্য থাকবে ইত্যাদি ইত্যাদি। এরপর সিদ্ধান্ত নিতে হবে কি কি টুলস ব্যবহার করবো, প্রোগ্রামিং ভাষা কি হবে, সফটয়্যারের প্লাটফরম কি হবে ইত্যাদি। এই প্রত্যেকটি বিষয় নিয়ে ভবিষ্যতে আরো বিস্তারিত আলোচনা করা হবে। **টিমমেট বাছাই** কোন একটা সফটয়্যার প্রজেক্টে কাজ করার সবচেয়ে গুরুত্বপূর্ণ বিষয় হচ্ছে কাদের সাথে কাজ করা হবে সেটা ঠিক করা। কতজন নিয়ে কাজ করতে হবে, কারা কারা কাজ করবে, কার কি দায়ুত্ব হবে এসব আর কি। এ ব্যাপারে বিশাল বিশাল লেখা লিখে ফেলা যায়। আমার ইচ্ছা আছে ভবিষ্যতে এ নিয়ে বিস্তারিত পোস্ট দেয়া। --- # আবোল-তাবোল > আবোল-তাবোল চিন্তা। Published: 2012-11-24 URL: https://milon.im/post/abol-tabol.md অনেকদিন ধরেই ব্লগে কিছু লিখছি না। আজ হঠাৎ ইচ্ছে হলো লিখতে। যা মাথায় আসছে তাই লিখছি। এর কোনটারই কোন মানে নেই। মাঝে মধ্যে এমন হাওয়াই মিঠাই টাইপ লেখা লিখতে ইচ্ছা করে। এ ধরনের লেখা পড়তেও মজা। পড়া শেষ, সেই সাথে এর আবেদনও শেষ। লেখার বিষয়গুলো মাথার মধ্যে কুট কুট করে না। আমার প্রিয় অনেক কবি সাহিত্যিকের লেখার মধ্যেই এ ঝামেলাটা আছে। এদের লেখা পড়ে শেষ করে ফেলার পরও অনেকক্ষন ধরে মাথার মধ্যে বাজতে থাকে। এই দেশে যে আমরা এখনো বেঁচে আছি এটাই হচ্ছে সবচেয়ে বড় মিরাকল! প্রতিদিন অকারনে হাজার হাজার মানুষ মরছে। আশুলিয়ায় মারা গেল ১২৪ জন, চট্টগ্রামে মারা গেল প্রায় একশ, যদিও এসব নিয়ে পত্র-পত্রিকায় না না ধরনের বিভ্রান্তিকর লেখা প্রকাশিত হচ্ছে। এই যে এত দূর্ঘটনা হচ্ছে তাতে আমাদের কোন মাথাব্যাথা নেই। আমরা আমাদের আবেগ হারিয়ে ফেলছি। আগে এই বিষয়গুলো মনে খুব দাগ কাটত, এমন ছিটে ফোটা আচড়ও ফেলে না। আমরা বাঙ্গালিরা হচ্ছি গোল্ডফিসের মস্তিষ্কের অধিকারী। এই যে এত মানুষ মারা গেল, এ নিয়ে আমরা কিছুদিন খুব আলাপ-আলোচনা করবো, চায়ের কাপে ঝড় তুলবো, ব্লগ, ফেসবুক আর পত্রিকার পাতা হৃদয়স্পর্শী লেখার ভরিয়ে ফেলবো। টিভি চ্যানেলগুলোতে বিভিন্ন টকশো হবে, নানা জন নানা ধরনের পরামর্শ দেবেন। কিন্তু কয়েকদিন না যেতেই আমরা সবকিছু বেমালুম ভুলে যাবো। আবার এই ধরনের আরেকটি দূর্ঘটনা ঘটার আগে এই ঘটনার কথা আমাদের মনেই পড়বে না। বাংলাদেশ দলের খেলোয়ারেরা মনে হয় সেঞ্চুরি করতে ভুলে গেছে। পর পর এতগুলি নার্ভাস নাইটিজ দেখে নিজেরই নার্ভাস লাগছে। তবে দেশের ক্রিকেট যে এতটা উন্নতি করবে তা মাত্র ৫ বছর আগেও আমি ভাবতেই পারি নি। সাবাস বাংলাদেশ!!! মন মেজাজ পুরাই বিলা। ফাও ফাও ঝাড়ছে স্যাররা। তার উপর না না ধরনের আলগা প্যাড়া দেয়াও অব্যাহত রয়েছে। এরা নিজেদেরকে কি ভাবে আর আমাদেরকেই বা কি ভাবে? কারো উপর পুরো রাগ ঝাড়তে পারলে কলিজা শীতল হতো। আমি স্কুলে থাকার সময় একটা কথা খুব প্রচলিত ছিল, ঢাকা শহরে কাক আর কবির সংখ্যা সমান। কলেজে এসে দেখলাম এই কথায় কিছুটা মডিফিকেশন এসেছে। কবির যায়গা দখল করে নিয়েছে বিবিএ স্টুডেন্ট। গত কয়েকদিনে বিভিন্ন ঘটনায় মনে হচ্ছে সারা বাংলাদেশে কাউয়ার ছেড়ে ছাগুর সংখ্যা ঢেড় বেশি। --- # ঈদের চাঁদ দেখা নিয়ে কিছু কথা > ঈদের চাঁদ নিয়ে কিছু ভ্রান্ত ধারনা এবং তার যুক্তিখন্ডন নিয়ে আমার ভাবনা। Published: 2012-08-18 URL: https://milon.im/post/some-info-about-eid-moon.md আজকে যদি আকাশে শাওয়াল মাসের চাঁদ দেখা যেত তাহলে আগামীকাল হত ঈদুল ফিতর। আসলে চাঁদ দেখার সাথে সাথেই ঈদ শুরু হয়ে যায়, কারন হিজরী দিন শুরু হয় সূর্যাস্ত থেকে, যেমন ইংরেজি তারিখ শুরু হয় রাত ১২ টা থেকে, বাংলা তারিখ শুরু হয় সূর্যোদয় থেকে। কিন্তু আজকে বাংলাদেশের আকাশে চাঁদ দেখা যাবে না এটা আমি জানতাম। আসলে কবে আকাশে চাঁদ দেখা যাবে আর কবে যাবে না এটা নির্ভর করে পৃথিবীর সাথে চাঁদের অবস্থান আর সূর্যের আলো চাঁদের উপর কতটুকু পড়ে তার উপর। জ্যোতির্বিজ্ঞান আমাদেরকে বলে দিতে পারে, কবে পৃথিবীর কোন জায়গার আকাশে চাঁদ দেখা যাবে আর কোথায় কোথায় দেখা যাবে না। আসলে আজকে আমাদের দেশের আকাশে চাঁদ ছিল, কিন্তু তা আমরা খালি চোখে দেখতে পারি নি। এর কারন সাধারনত চাঁদ যদি দিগন্তরেখার ১০ ডিগ্রি বা তার উপরে থাকে তাহলে আমরা খালি চোখে তা দেখতে পারি, তবে তার জন্য চাঁদের কমপক্ষে ৪ শতাংশ জায়গায় সূর্যের আলো পড়তে হবে। কিন্তু আজ আমাদের দেশের আকাশে চাঁদ ছিল দিগন্ত রেখার মাত্র ২ ডিগ্রি উপরে আর চাঁদের ২ শতাংশে মাত্র সূর্যের আলো পড়েছিল। তাই আমরা চাঁদ দেখতে পাই নি। আগামীকাল কিন্তু আমরা ঠিকই চাঁদ দেখবো, এবং কালকে বাংলাদেশের আকাশে চাঁদে প্রায় ১ ঘন্টা ১০ মিনিট ধরে দেখা যাবে, কালকে চাঁদ অবস্থান করবে দিগন্তরেখার ১১ ডিগ্রি উপরে। একইভাবে বলে দেয়া যায় কবে ঈদুল আযহা হবে। কোরবানীর ঈদ হবে অক্টোবর মাসের ২৮ তারিখ। একটা জিনিস লক্ষ করলে আমরা দেখবো, আমাদের দেশে প্রতিবছর আমাদের দেশে ঈদ হয় সৌদি আরবের ১ দিন পর অথচ সৌদি আরবের সাথে আমাদের সময়ের পার্থক্য মাত্র তিন ঘন্টা। সে হিসেবে আমেরিকার ৪ দিন পর আমাদের ঈদ হওয়ার কথা কারন সময়ের পার্থক্য প্রায় ১২ ঘন্টা কিন্তু ঈদ হয় ২ দিন পর। এর কারনও কিন্তু চাঁদের অবস্থানের উপরেই লুকিয়ে আছে। আপনারা যদি ভয়েজার স্কাই গ্যাজার বা গুগোল স্কাই ম্যাপ ব্যবহার করেন তাহলে এই বিষয়গুলো একদমই পরিষ্কার হয়ে যাবে। এ কারনেই হিজরী বছর ৩৫৫ দিনে হয়, ৩৫৪ বা ৩৫৭ দিনে না। মাঝে মাঝে অবশ্য ৩৫৬ দিনে হয় এর কারনও কিন্তু চাঁদ-সূর্যের অব্স্থানের উপরেই নির্ভর করছে। লিপ ইয়ার যে কারনে হয় হিজরী সনও সে কারনেই ৩৫৬ দিনে হয়। আমার লেখায় কিছুটা ভুল থাকতে পারে, কারন এর বেশিরভাগই স্মৃতি থেকে লেখা। ভুলত্রুটি ক্ষমাসুন্দর দৃষ্টিতে দেখলে এবং ধরিয়ে দিলে খুশি হবো। > এই টপিকের কৃতজ্ঞতা [অনুসন্ধিৎসু চক্র](http://achokro.org) বিজ্ঞান সংগঠনের নাইমুল ইসলাম অপু ভাইয়ের কাছে যিনি আমাকে জ্যোতির্বিজ্ঞান সম্পর্কে আগ্রহী করে তুলেছেন এবং প্রয়াত ভাষাবিদ ড. হুমায়ূন আজাদের প্রতি যার বই পড়ে আমি এই সব হিসাব-নিকাশ শিখেছি। --- # সহজে পাইথন শেখা-০৭ > সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (সপ্তম পর্ব) Published: 2012-07-06 URL: https://milon.im/post/learn-python-easily-07.md আমরা এতদিন শুধুমাত্র আমাদের দেয়া ভ্যালু নিয়েই কাজ করেছি। কিন্তু কম্পিউটার প্রোগ্রামে দেখা যায় আমরা ইউজারের কাছ থেকে বিভিন্ন তথ্য সংগ্রহ করে থাকি। যেমন- আমরা হয়ত ইউজারের কাছ থেকে তার নাম, বয়স ইত্যাদি জানতে চাইতে পারি। এটা পাইথনে করা খুবই সহজ। ছোট্ট একটা উদাহরন দেখি- ``` >>>print “What is your name?” >>>name=raw_input() >>>print “Hoe old are you?” >>>age=raw_input() >>>print “Hello %s, you are %s years old.” % (name, age) ``` উপরের প্রোগ্রামটি ইউজারের কাছ থেকে তার নাম এবং বয়স জানতে চাইবে এবং সবশেষে সে তার নাম এবং বয়স প্রদর্শন করবে। এক্ষেত্রে একেক ব্যবহারকারী একেক ধরনের ইনপুট দেবে, কিন্তু আমাদের প্রোগ্রাম সে সকল ধরনের ইনপুট নিয়েই কাজ করতে পারবে। আর একটা বিষয়, আমরা অনেক বড় বড় প্রোগ্রাম করার সময় চাইলে প্রোগ্রাম কোডে বিভিন্ন কমেন্ট লিখে রাখতে পারি। যা পরবর্তীতে আমাদেরকে ঐ প্রোগ্রাম দেখা মাত্রই বুঝতে সাহায্য করবে। এছাড়া বড় বড় প্রজেক্টে দেখা যায় অনেকে মিলে একটা প্রোগ্রাম তৈরী করে। সেক্ষেত্রে একজনের কোড অন্যজনের বুঝতে অসুবিধা হতে পারে। তাই কমেন্ট ব্যবহার করলে এক্ষেত্রে সুবিধা পাওয়া যাবে। উপরের উদাহরনটিই আমরা কমেন্ট ব্যবহার করার পরের অবস্থা দেখি- ``` >>>#This is a sample program >>>print “What is your name?” #ask name >>>name=raw_input() #take input as name >>>print “Hoe old are you?” #ask age >>>age=raw_input() #take input as age >>>#Next line will print the values >>>print “Hello %s, you are %s years old.” % (name, age) ``` কমেন্ট ব্যবহার করার পর যে কেউ প্রোগ্রামটি দেখলেই বুঝতে পারবে এটা দিয়ে কি কাজ করা হচ্ছে। পাইথনে কমেন্ট করার জন্য হ্যাশ(#) ব্যবহার করা হয়। হ্যাশ চিহ্ন পাওয়ার পর পাইথন ইন্টারপ্রিটার ঐ লাইনের আর কোন কোডকে কম্পাইল করে না। --- # সহজে পাইথন শেখা-০৬ > সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (ষষ্ঠ পর্ব) Published: 2012-07-05 URL: https://milon.im/post/learn-python-easily-06.md আমাদের আজকের টপিক হচ্ছে স্ট্রিং। পাইথনে স্ট্রিং হচ্ছে একটা অবজেক্ট। আসলে পাইথন একটা অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং ভাষা। এখানে সবকিছুই আসলে এক-একটা অবজেক্ট। অবজেক্ট সম্পর্কে আমরা পরে বিস্তারিত জানবো। স্ট্রিং হচ্ছে এক বা একাধিক ক্যারেকটারের সমষ্টি। আমরা স্টিং তৈরী করতে পারি যে কোন কিছু সিঙ্গেল বা ডাবল কোটেশনের মধ্যে লিখে। যেমন- ``` “My name is Milon.” 'I am a student of Information Technology.' ``` আমরা স্ট্রিংকে একটা ভ্যারিয়েবল হিসেবে ধরতে পারি। যেমন- ``` >>>name=”My name is Milon.” >>>print name My name is Milon. ``` এছাড়া মাল্টিলাইন স্ট্রিংও হতে পারে। মাল্টিলাইন স্ট্রিং লেখা হয় তিনটা সিঙ্গেল বা ডাবল কোটেশন ব্যবহার করে। যেমন- ``` >>>”””This is a multi line String. ...This is the second line. ...This is the last line of the string.””” ``` মাল্টিলাইন স্ট্রিং লেখার সময় আমরা পাইথন টার্মিনালে তিনটা করে ডট(. . .) দেখতে পাব। আমরা স্ট্রিং দিয়ে মাল্টিপ্লিকেশন বা গুন অপারেটর ব্যবহার করে অনেক কিছু লিখতে পারি। যেমন- ``` >>>”Milon”*5 MilonMilonMilonMilonMilon ``` এবারে আমরা স্ট্রিংএর আরেকটা মজার ব্যবহার শিখবো। আমরা স্ট্রিংএ % নোটেশনকে প্লেসহোল্ড ক্যারেকটার হিসেবে ব্যবহার করতে পারি। যেমন- ``` >>>string=”Hello %s, How are you?” >>>print string % Milon Hello Milon, How are you? ``` আমরা চাইলে একাধিক ভ্যারিয়েবলও ব্যবহার করতে পারি। যেমন- ``` >>>name1=”Rahim” >>>name2=”Karim” >>>print “%s and %s are two brothers.” % (name1, name2) Rahim and Karim are two brothers. ``` স্ট্রিং একটা প্রোগ্রামিং ভাষার একটা অত্যন্ত গুরুত্বপূর্ণ অংশ। ছোট্ট একটা টিউটোরিয়াল স্ট্রিংয়ের মত বিশাল বিষয়কে জানার জন্য মোটেও যথেষ্ট না। ফাংশন, লিস্ট আর টাপল সম্পর্কে জানার পর আমরা স্ট্রিং সম্পর্কে আরো বিস্তারিত জানবো। --- # সহজে পাইথন শেখা-০৫ > সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (পঞ্চম পর্ব) Published: 2012-07-04 URL: https://milon.im/post/learn-python-easily-05.md এতদিন পর্যন্ত আমরা সরাসরি বিভিন্ন সংখ্যা নিয়ে কাজ করেছি। আজ আমরা দেখবো ভ্যারিয়েবল নিয়ে কিভাবে কাজ করতে হয়। ভ্যারিয়েবল শব্দটা মনে হয় বেশ ভারিক্কি হয়ে গেছে। এটাকে বাংলাতে বলে চলক। যেমন, মনে করি "রহিম" বা "করিম"। আমরা যদি রহিম বা করিম দিয়ে তাদের বয়স প্রকাশ করতে চাই, যেমন- রহিমের বয়স ২০ আর করিমের বয়স ১৮ তাহলে আমাদেরকে লিখতে হবে- ``` রহিম = ২০ করিম = ১৮ ``` তাদের বয়স যদি ২০ আর ১৮ না হয়ে ২৫ আর ৩০ হয় তাহলে লিখতে হবে- ``` রহিম=২৫ করিম=৩০ ``` এটাই হচ্ছে ভ্যারিয়েবল যার মান পরিবর্তিত হতে পারে। পাইথনে ভ্যারিয়েবল লেখার পদ্ধতিটিও উপরের মতই। যেমন- ``` >>>rahim=20 >>>karim=18 ``` এখন প্রশ্ন হচ্ছে ভ্যারিয়েবল তৈরী করে আমাদের লাভ কি? আমাদেরকে প্রশ্ন করা হল, রহিম এবং করিমের মোট বয়স কত? তখন আমরা এর উত্তর দেব- ``` >>>rahim=20 >>>karim=18 >>>rahim+karim 38 ``` এখন যদি রহিম বা করিমের বয়স আমরা পরিবর্তনও করি তবুও `rahim+karim` স্টেটমেন্ট ব্যবহার করে আমরা তাদের বয়স বের করতে পারবো। এটাই হচ্ছে ভ্যারিয়েবলের সুবিধা। আরও অনেক প্রশ্ন থেকে যায়। ভ্যারিয়েবলের নাম কি শুধু `rahim` বা `karim` ই দেব নাকি অন্য নামও দেয়া যায়? এর উত্তর হচ্ছে যে কোন নামই দেয়া যায়। তবে নামে শুধুমাত্র লেটার, নাম্বার আর আন্ডারস্কোর(`_`) ব্যবহার করা যাবে। নাম দেয়ার ক্ষেত্রে একটা বিষয় খেয়াল রাখা উচিৎ, নাম অর্থপূর্ণ হওয়া উচিৎ যাতে নাম দেখেই এটা কি সেটা বোঝা যায়। যেমন- ``` >>>no_of_students=50 >>>marks_in_math=75 ``` তবে অনেক বড় নাম দেয়া সুবিধাজনক না। যেমন- ``` >>>this_is_also_a_variable_but_not_so_useful=0 ``` এছাড়াও প্রত্যেক ল্যাংগুয়েজেরই কিছু নিজস্ব সংরক্ষিত শব্দ আছে। এদেরকে বলে কী-ওয়ার্ড। পাইথনে এমন কী-ওয়ার্ড আছে ২৯ টি। এদেরকেও ভ্যারিয়েবলের নাম হিসেবে ব্যবহার করা যাবে না। এই কী-ওয়ার্ডগুলো হচ্ছে- and | assert | break | class | continue ------ | ------- | ----- | ----- | -------- def | del | elif | else | except exec | finally | for | from | global if | import | in | is | lambda not | or | pass | print | raise return | try | while | yield | - আরো প্রশ্ন আছে। ভ্যারিয়েবলে কি শুধু নাম্বারই রাখা যায় নাকি অন্যান্য জিনিসও রাখা যায়? উত্তর হচ্ছে ভ্যারিয়েবলে যে কোন কিছুই রাখা যায়, যেমন- নাম্বার, ক্যারেকটার, স্ট্রিং(অনেকগুলো ক্যারেকটারের সমষ্টি) এমনকি অন্যান্য ভ্যারিয়েবলও রাখা যায়। যেমন- ``` >>>name=”Nuruzzaman Milon” >>>Dept='ICT' ``` খেয়াল রাখা দরকার, স্ট্রিং লেখার সময় এটাকে অবশ্যই ডাবল কোটেশনের (" ") বা সিঙ্গেল কোটেশনের(' ') মধ্যে লিখতে হয়। আমরা ভবিষ্যতে স্ট্রিং নিয়ে আরো বিস্তারিত জানবো। এবার আমরা জানবো ভ্যারিয়েবলের টাইপ সম্পর্কে। যেমন- 2 বা 5 হচ্ছে integer টাইপের ভ্যারিয়েবল, 2.5 বা 8.9 হচ্ছে float টাইপের ভ্যারিয়েবল। কোন ভ্যারিয়েবলের টাইপ জানার জন্য আমরা ব্যবহার করবো type() নামের একটা ফাংশন। এই ফাংশনের ব্র্যাকেটের ভেতরে ভ্যারিয়েবলের নাম লিখলেই সেটা কোন টাইপের ভ্যারিয়েবল সেটা বলে দেবে। যেমন- ``` >>>type(5) >>>type(8.9) >>>type(“Python”) ``` --- # সহজে পাইথন শেখা-০৪ > সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (চতুর্থ পর্ব) Published: 2012-07-03 URL: https://milon.im/post/learn-python-easily-04.md আজকে আমরা দেখবো পাইথনে কিভাবে হিসাব-নিকাশ করতে হয়। হিসাবের কথা আসলেই প্রথমে আমাদের মনে আসে যোগ-বিয়োগের কথা। পাইথনে যোগ, বিয়োগ, গুন ভাগ করা খুবই সহজ। প্রথমেই আসে যোগের কথা। পাইথনে দুইটা সংখ্যা যোগ করতে হলে লিখতে হয়- ``` >>>2+8 10 >>>5+27 32 ``` একইভাবে তিন, চার বা পাঁচটা সংখ্যাও যোগ করা যায়। ``` >>>2+9+7 18 ``` বিয়োগ গুন বা ভাগও একই ভাবে করা যায়। যেমন- ``` >>>5-3 2 >>>5*4 20 >>>25/5 5 ``` পাইথনে যোগ, বিয়োগ, গুন বা ভাগ করার জন্য যেসব নোটেশন ব্যবহার করা হয় তা হল-
- যোগঃ `+` - বিয়োগঃ `–` - গুনঃ `*` - ভাগঃ `/` এখানে ভাগ করার সময় একটা জিনিস লক্ষ্য করি- ``` >>>10/3 3 >>>11/2 5 ``` যদিও উপরের দুইটি ক্ষেত্রে আসা উচিৎ ছিল- ``` 3.33333333 5.5 ``` আসলে শুধু পাইথনে না, যে কোন প্রোগ্রামিং ল্যাংগুয়েজেই ভাগ করার সময় এভাবে নিঃশেষে বিভাগ্য অংশটুকু রেখে বাকি অংশটা নিয়ে কাজ করা হয়। আমরা যদি আসল উত্তরটা পেতে চাই তাহলে আমাদের যেটা করতে হবে সেটাকে প্রোগ্রামিং ল্যাংগুয়েজের ভাষায় বলা হয় কাস্টিং। অন্যান্য ল্যাংগুরয়েজের চেয়ে এ জায়গাতেও পাইথন অনেক সহজ। যেমন- ``` >>>10.0/2 3.33333333 >>>10/3.0 3.33333333 ``` যেখানে C, C++ বা Java তে কাস্টিং করার নিয়ম- ``` (float)10/3 or (double)10/3 ``` এবার আর একটা মজার জিনিস শিখি। আমাদের যে সবসময় ভাগফলই লাগবে তা কিন্তু না। আমাদের অনেকসময় ভাগশেষও বের করার দরকার পড়তে পারে। এর জন্য আমরা যে অপারেটর ব্যবহার করবো সেটাকে বলে মডুলাস। যেমন- ``` >>>10%3 1 >>>17%5 2 ``` এটা প্রকাশ করা হয় % চিহ্ন দ্বারা। এবার আমরা দেখবো, কিভাবে এক্সপোনেনশিয়াল বা ঘাত বের করতে হয়। যেমন ২^৪ মান বের করবো। এর জন্য লিখতে হবে- ``` >>>2**3 8 >>>4**5 1024 ``` এক্সপোনেনশিয়াল বের করার জন্য আমরা ব্যবহার করবো জোড়া এস্টেরিক্স(`**`)। আজকে আমরা যতগুলো অপারেটর দেখলাম তার সবই বাইনারী অপারেটর, অর্থাৎ এগুলো নিয়ে কাজ করতে চাইলে কমপক্ষে দুইটা অপারেন্ড লাগবে। যেমন `+` বা `*` অপারেটর ব্যবহার করতে হলে কমপক্ষে দুইটা সংখ্যা লাগবে। এবার আসবে অপারেটরের অর্ডার। আমরা ছোট্ট একটা উদাহরন দেখি- ``` >>>5+30*20 605 >>>(5+30)*20 700 ``` অর্থাৎ একই স্টেটমেন্ট শুধুমাত্র ব্র্যাকেটের কারনে দুই ধরনের ফলাফল দিচ্ছে। এর কারন সহজ। প্রত্যেকটা অপারেটরেরই কাজ করার একটা ক্রম থাকে। যেমন আমরা যদি একটা স্টেটমেন্ট লিখি- ``` >>>2+5-3*7/4%2**4 2 ``` এক্ষেত্রে প্রথমে কাজ করেছে এক্সপোনেনশিয়াল(`**`), তারপর ভাগ(`/`), তারপর গুন(`*`), এরপর মডুলাস(`%`) এবং শেষে যোগ(`+`) এরপর সবশেষে বিয়োগ(`-`)। উপরের ক্রমটাই হচ্ছে অপারেটরগুলোর ওয়ার্কিং অর্ডার। বাই ডিফল্ট অপারেটরগুলো এই ক্রম অনুসারেই কাজ করে। আমরা চাইলে প্রয়োজনমত ব্র্যাকেট ব্যবহার করে আমাদের ইচ্ছামত হিসাব করতে পারি। --- # সহজে পাইথন শেখা-০৩ > সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (তৃতীয় পর্ব) Published: 2012-06-29 URL: https://milon.im/post/learn-python-easily-03.md আমি এখন পর্যন্ত যতগুলো প্রোগ্রামিং ল্যাংগুয়েজ শিখেছি সবগুলোতেই প্রথম প্রোগ্রাম লিখেছিলাম Hello World এই শব্দদুটি প্রিন্ট করার মাধ্যমে। এটা আসলে একটা ট্রেডিশন হয়ে গেছে। পাইথনেও প্রথম প্রোগ্রাম করবো এই শব্দদুটিই প্রিন্ট করে। আমি আগেও বলেছি প্রোগ্রামিং শুরু করার জন্য পাইথন খুবই উপযোগী একটা প্রোগ্রামিং ল্যাংগুয়েজ। অন্য ল্যাংগুয়েজে এই শব্দদুটি লেখার জন্য যেখানে অনেক কিছু লিখতে হয় পাইথনে মাত্র কয়েকটা শব্দ লিখলেই সে কাজ করা যায়। একটা উদাহরন দেই- Hello World শব্দদুইটা C, C++, Java এবং Python এই চারটা প্রোগ্রামিং ল্যাংগুয়েজে লিখে তুলনা করি- ``` #include int main(){ printf(“Hello World”); return 0; } ``` Hello World in C++: ``` #include using namespace std; int main(){ cout<<”Hello World”; return 0; } ``` Hello World in Java: ``` public static void main(String args[]){ System.out.println(“Hello World”); } ``` Hello World in Python: ``` print “Hello World” ``` বোঝাই যাচ্ছে অন্য যে কোন ল্যাংগুয়েজের তুলনায় পাইথনে কোড করা কত সহজ। আমরা কিন্তু ইতোমধ্যে পাইথনে আমাদের প্রথম কোড করে ফেলেছি। শুধু Hello World না, এই print স্ট্যাটমেন্ট দিয়ে আমরা পাইথন শেলে যে কোন কিছুই প্রিন্ট করতে পারি। যেমন আমি যদি আমার নাম ধাম প্রিন্ট করতে চাই, তাহলে প্রোগ্রামটি হবে- ``` print “Nuruzzaman Milon” print “Student of Information and Communication Technology” print “Mawlana Bhashani Science and Technology University” ``` এ তো গেল আমি পাইথন শেলে কিভাবে কোড লিখবো সেটা। পাইথন শেল বন্ধ করে দিলেই তো আমার লেখা সব কোড মুছে যাবে। বার বার এই কোড কি আমি লিখবো? না, বার বার একই কোড লেখার কোন দরকার নেই। আমি আমার কোড খুব সহজেই একটা টেক্সট ফাইলে সংরক্ষন করে রাখতে পারি। তবে এক্ষেত্রে ফাইলের এক্সটেনশন হতে হবে `.py` যেমন আমি যদি উপরের প্রোগ্রামটি সংরক্ষন করে রাখতে চাই তাহলে আমি সেটিকে, ধরা যাক name নামে সংরক্ষন করবো, সেক্ষেত্রে ফাইলের নাম হবে `name.py` এবার আমি যদি ফাইলটি আবার চালাতে চাই তাহলে আমাকে পাইথন শেলে লিখতে হবে- ``` python name.py ``` তাহলেই আমি পাইথন শেলে আমার কাঙ্খিত ফলাফল দেখতে পারবো। --- # সহজে পাইথন শেখা-০২ > সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (দ্বিতীয় পর্ব) Published: 2012-06-05 URL: https://milon.im/post/learn-python-easily-02.md আগের পর্বে আমি পাইথন নিয়ে প্রাথমিক কিছু আলোচনা করেছিলাম। এই পর্বে আমরা দেখবো কিভাবে আমরা আমাদের পিসিকে পাইথনে কোড করার উপযোগী করতে পারি। প্রথমেই পাইথনের ওয়েব সাইট () থেকে পাইথন ডাউনলোড করতে হবে। সেথানে পাইথনের দুইটা ভার্সনের নাম দেয়া আছে। একটা ২.৭.৩ অন্যটা ৩.২.৩। এর মধ্য থেকে আমরা ২.৭.৩ ব্যবহার করব। প্রশ্ন উঠতে পারে, কেন আমরা নতুন ভার্সন থাকতে পুরাতন ভার্সন ব্যবহার করব। এর উত্তর হচ্ছে পাইথনের কোডিং স্টাইলে ভার্সন ৩ থেকে বেশ কিছু পরিবর্তন এসেছে যা আগের ভার্সনের সাথে কনফ্লিক্ট করে। আর পাইথনের যে সকল ফ্রেমওয়ার্ক আছে, তার অধিকাংশই এখন পর্যন্ত পাইথন ৩ সাপোর্ট করে না। তাই আমরা পাইথন ২.৭ ই শিখবো। একবার শিখে ফেললে ভবিষ্যতে প্রয়োজনবোধে নিজেদেরকে পাইথনের নতুন ভার্সনে আপডেট করে নিতে মনে হয় না আমাদের খুব একটা কষ্ট হবে। এখন কথা হচ্ছে আমরা কোন অপারেটিং সিস্টেমে পাইথনের কোড করবো। আমার জানামতে উইন্ডোজই পৃথিবীর একমাত্র ওএস যেখানে বিল্ট ইন পাইথন সাপোর্ট নেই। যাই হোক আমি যদি উইন্ডোজ ব্যবহারকারী হই তাহলে প্রথমেই আমি পাইথনের ওয়েব সাইট থেকে পাইথনের ২.৭.৩ ভার্সনের এক্সিকিউটেবল ফাইল ডাউনলোড করে নিব। এই এক্সিকিউটেবল ইনস্টল করলে দেখবো আইডিএলই নামে একটা এডিটর সেটআপ হয়েছে। এই আইডিএলই ব্যবহার করেই আমরা কোড করবো। এছাড়া কেউ চাইলে নোটপ্যাড++ ব্যবহার করতে পারেন। আপনি লিনাক্স মিন্ট বা উবুন্টু ব্যবহারকারী হয়ে থাকলে আপনার টার্মিনাল ওপেন করে লিখুন- ``` python ``` তাহলেই আপনি কোড লিখতে পারবেন। আইডিএলই ইনস্টল দিতে লিখুন- ``` sudo apt-get install idle ``` এবার আপনার পিসিতে পাইথন ঠিকভাবে ইনস্টল হয়েছে কিনা দেখতে চাইলে টার্মিনাল ওপেন করে লিখুন python তারপর এন্টার দিন। যদি দেখেন টার্মিনালে নিচের লেখাটুকু এসেছে তাহলে বুঝবেন আপনার পাইথন সেটআপ করা ঠিক আছে। ``` Python 2.7.3 (r266:84292, Sep 15 2010, 15:52:39) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. ``` বিভিন্ন পিসিতে এই লেখাটুকু ভিন্ন রকম হতে পারে। ব্যস আপনার পিসি এখন পাইথনে কোড করার উপযোগী। --- # সহজে পাইথন শেখা-০১ > সহজ ভাষায় পাইথন শেখার টিউটোরিয়াল। (প্রথম পর্ব) Published: 2012-06-04 URL: https://milon.im/post/learn-python-easily-01.md অনেকদিন ধরেই ইচ্ছা ছিল পাইথন নিয়ে লিখব। এটা আমার খুব পছন্দের একটি প্রোগ্রামিং ভাষা। প্রথেমই একটা মজার তথ্য দেই। আমরা অনেকেই মনে করি পাইথন মানে অজগর। আসলে পাইথন হচ্ছে ময়াল সাপ। এই ময়াল সাপ যে কি জিনিস তা অবশ্য আমি জানি না। তবে অজগর হচ্ছে Boa. আসলে একেবারে পাইথন নিয়ে লেখা সম্ভব না, আমি বিভিন্ন পর্বে ভাগ ভাগ করে এটা নিয়ে লিখব। পাইথন আমার পছন্দের, এর পেছনে অনেকগুলো কারন আছে। প্রথমেই হচ্ছে পাইথন একটা ওপেন সোর্স প্রজেক্ট। এটা প্লাটফরম ইন্ডিপেন্ডেন্ট আর পোর্টেবল, এক অপারেটিং সিস্টেমে লেখা কোড কোন ধরনের পরিবর্তন ছাড়াই যে কোন অপারেটিং সিস্টেমে চলতে পারে। এটা সোর্স হতে কম্পাইল ছাড়াই সরাসরি রান করতে পারে, পিএইচপি, জাভাস্ক্রীপ্ট বা অন্যান্য স্ক্রীপ্টিং ল্যাংগুয়েজের মত। এটা অনেক সহজ, অনেকটাই ন্যাচারাল ল্যাংগুয়েজের সাথে সামঞ্জস্যপূর্ণ। এটা অবজেক্ট অরিয়েন্টেড তবে জাভার মত স্ট্রীক্টলি অবজেক্টে অরিয়েন্টেড না। অর্থাৎ প্রসিডিউরাল ল্যাংগুয়েজের মতও কোড করা যায়। এরকম আরো বহু কারন আছে। এখন কয়েকটা প্রশ্ন নিশ্চই মনে এসে দাড়িয়েছে। ন্যাচারাল ল্যাংগুয়েজ কি, অবজেক্ট অরিয়েন্টেড ল্যাংগুয়েজ কি, প্রসিডিউরাল ল্যাংগুয়েজ কি? একটা একটা করে উত্তর দেয়ার চেষ্টা করি। ন্যাচারাল ল্যাংগুয়েজ ও ফরমাল ল্যাংগুয়েজঃ ন্যাচারাল ল্যাংগুয়েজ হচ্ছে আমরা মানুষজন যে ভাষায় কথা বলি, যেমন বাংলা, ইংরেজি, আরবি ইত্যাদি। আর ফরমাল ল্যাংগুয়েজ হচ্ছে আমাদেরই তৈরী বিশেষ ভাষা যা বিভিন্ন ধরনের কাজের জন্য তৈরী করা হয়েছে। যেমন- গাণিতিক বিভিন্ন ধরনের নোটেশন ব্যবহার করে আমরা একটা স্টেটমেন্ট তৈরী করি, বিভিন্ন রাসায়নিক বিক্রিয়া বোঝাতে আমরা বিভিন্ন ধরনের রাসায়নিক সংকেত ব্যবহার করি ইত্যাদি। কম্পিউটারের প্রোগ্রামিং ভাষাও এই ধরনেরই একটা ফরমাল ল্যাংগুয়েজ। প্রসিডিউরাল ও অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং ল্যাংগুয়েজঃ ধরুন একটা প্রোগ্রাম ১০ লাইনের। যদি প্রোগ্রামের এক্সিকিউশন এভাবে হয় যে, প্রথমে ১ তারপর ২ এভাবে বাকি লাইনগুলো কাজ করে তাহলে সেটা হচ্ছে প্রসিডিউরাল ল্যাংগুয়েজ। আর অবজেক্ট অরিয়েন্টেড ল্যাংগুয়েজ হচ্ছে যেখানে প্রতিটা প্রোগ্রাম অবজেক্ট ধরে ধরে কাজ করে। এ ব্যাপারে পরে আরো বিস্তারিত আলাপ করব। আজ এই পর্যন্তই। পরবর্তীতে বাকিটা আলোচনা করব। --- # লিনাক্সে ব্যবহার করুন গুগোল ড্রাইভ > লিনাক্স বেজড অপারেটিং সিস্টেমে গুগল ড্রাইভ ব্যবহার করার পদ্ধতি। Published: 2012-04-25 URL: https://milon.im/post/use-google-drive-in-linux.md সকাল বেলাই মেজাজ খারাপ হয়ে গেল। গুগোল এন্ড্রয়েড(লিনাক্সের জন্য উইএসবি ড্রাইভার নাই), পিকাসার(সাপোর্ট বন্ধ) পর এবার তাদের নতুন সার্ভিস গুগোল ড্রাইভেও লিনাক্স ব্যবহারকারীদের জন্য কিছুই রাখে নি। আমরা যারা ২৪/৭ লিনাক্স ব্যবহার করি তারা কি আঙ্গুল চুষবো? যাইহোক, ফেবুতে [অঞ্জন দা](https://www.facebook.com/anjan011)'র দেয়া একটা লিঙ্কে দেখলাম লিনাক্সেও নাকি গুগোল ড্রাইভের সেবা ব্যবহার করা যাবে। ঝটপট ট্রাই দিলাম। কাজও হল। কি কি করা লাগবে আসুন জেনে নেই। প্রথমেই আপনাকে নতুন রিপো এড করতে হবে। টার্মিনালে লিখুন- ``` sudo add-apt-repository ppa:invernizzi/google-docs-fs ``` এরপর আপডেট করতে লিখুন- ``` sudo apt-get update ``` এবার ইনস্টল করুন- ``` sudo apt-get install google-docs-fs ``` এবার হোম ফোল্ডারে Drive নামের একটা ফোল্ডার তৈরী করুন। এবার একে একে নিচের কোডগুলো টার্মিনালে লিখুন- ``` cd Drive gmount Drive username@gmail.com ``` username এর জায়গায় আপনার ইউজারনেম লিখুন, তারপর পাসওয়ার্ড দিন। ব্যস এই ড্রাইভ ফোল্ডারে আপনার গুগোল ড্রাইভ মাউন্টেড হবে। [সূত্র](http://www.omgubuntu.co.uk) --- # শুভ নববর্ষ... > বাংলা নববর্ষ ১৪১৯ এর শুভেচ্ছা। Published: 2012-04-13 URL: https://milon.im/post/shuvo-noboborsho-1419.md ![শুভ নববর্ষ](/assets/images/posts/shuvo-noboborsho.jpg) শুভ নববর্ষ, ১৪১৯ বঙ্গাব্দ। সবাইকে নতুন বছরের শুভেচ্ছা। নতুন বছর সবার জীবনে বয়ে আনুক সুখ-সমৃদ্ধি। পুরাতন বছরের জরা-ক্লেষ ভুলে গিয়ে সবাই নতুন স্বপ্নে বাঁচতে শিখবে এই প্রত্যাশা। --- # শুভ নববর্ষ, ২০১২ > New years greetings of 2012. Published: 2012-01-01 URL: https://milon.im/post/happy-new-year-2012.md ![Happy New Year 2012](/assets/images/posts/happy-new-year-2012.jpg) দেখতে দেখতে আরো একটি বছর জীবন থেকে বিদায় নিয়ে গেল। প্রাপ্তি-অপ্রাপ্তির হিসেব করলে হয়ত প্রাপ্তিই বেশি হবে। আমি আশাবাদী মানুষ, আশা করছি নতুন বছরে প্রাপ্তির তালিকা আরো বড় হবে। দেশের রাজনৈতিক পরিস্থিতির উন্নতি হবে, অর্থনৈতিক স্থিতিশীলতা আসবে, লেখাপড়ার মানের আরো উন্নতি হবে। সবাইকে ইংরেজি নতুন বছরের শুভেচ্ছা। Happy New Year, 2012. --- # বিজয় দিবসের শুভেচ্ছা > সবাইকে বিজয় দিবসের শুভেচ্ছা। Published: 2011-12-16 URL: https://milon.im/post/victory-day-greetings.md ![বিজয় দিবসের শুভেচ্ছা](/assets/images/posts/victory-day.jpg) আজ আমাদের দেশের স্বাধীনতার চল্লিশ বছর পূর্তি হয়েছে। বিজয়ের এ দিনে আমরা দেশের জন্য কি করছি? আমরা কি পারি না এ দেশটাকে ভালবেসে আমাদের কাজগুলোকে ঠিকঠাকমত করতে। দেশের প্রতি ভালবাসা দেখানোর এখনই তো সময়। শুধু মুখে বড় বড় বুলি না আওড়ে আমরা দেশের জন্য প্রতিদিন অন্তত একটা করে কাজ করি। আজ থেকে কি আমরা পারি না আমাদের দেশের শিল্প-সংস্কৃতিকে পৃষ্ঠপোষকতা করতে, পারি নি হিন্দি চ্যানেলগুলোকে বাদ দিয়ে আমাদের দেশীয় চ্যানেলগুলোকে দেখতে, পারি না বিদেশি পোষাক না কিনে আমাদের দেশীয় পোষাক পড়তে? আজ থেকে আমরা কেন প্রতিজ্ঞা করছি না যে আমরা এখন থেকে শুদ্ধ বাংলায় কথা বলব, বাংলা বানানগুলোর দিকে একটু নজর রাখব? মুক্তিযুদ্ধে তিরিশ লক্ষ শহীদ প্রাণ দিয়েছেন, আমরা আমাদের ছোট ছোট কাজগুলো দিয়ে দেশের জন্য কিছু একটা অন্ততঃ করি। সবাইকে বিজয় দিবসের শুভেচ্ছা... --- # উবুন্টু বা মিন্টে পুরাতন সফটয়্যার ইনস্টলেশন > উবুন্টু এবং লিনাক্স মিন্ট অপারেটিং সিস্টেমে পুরাতন সফটয়্যার ব্যবহার করার পদ্ধতি। Published: 2011-09-07 URL: https://milon.im/post/install-older-software-in-ubuntu-and-linux-mint.md আপনি এত কস্ট করে উবুন্টু/মিন্টে বিভিন্ন সফটওয়্যার ইনস্টল করেছেন কিন্তু নতুন করে আবার উবুন্টু/মিন্ট ইনস্টল করলেই সবই শেষ। আবার অন্য পিসিতে উবুন্টু/মিন্ট সেট আপ করলেন কিন্তু প্রোয়জনীয় সফটওয়্যার ইন্টারনেট সংযোগ ছাড়া দিতে পারছেন না। এই সমস্যা সমাধানের জন্য আপনাকে শুধু ছোট একটা কাজ করতে হবে। আমরা যে সকল সফটওয়্যার ইনস্টল করি তা সাধারনত জমা থাকে এখানে- ``` file system/var/cache/apt/archieves ``` এটাকে বলা হয় উবুন্টু/ মিন্টের লোকাল রিপোজিটরি। প্রথমে আমাদের করণীয় হচ্ছে যা তাহলো আমাদের ডাউনলোডকৃত সফটওয়্যার সমূহ archieves ফাইল থেকে হার্ড ডিস্কের যে-কোন নিরাপদ জায়গাতে রাখি। যদি নরমালি কপি করা যায় না তখন রুট পারমিশন নিয়ে করতে হতে পারে। সেজন্যে- `alt+f2` চেপে application launcher এ গিয়ে `gksu nautilus` লিখে এন্টার দিতে হবে। অথবা টার্মিনালে গিয়ে লিখুন- ``` gksudo nautilus ``` অত:পর ফাইল গুলো কপি করে রাখুন। এখন নতুন পিসি বা যে পিসিতে সফটওয়্যার সমূহ ইনস্টল করতে চান তার ডেস্কটপে ফাইলটা কপি করে রাখুন এখন টার্মিনালে লিখুন- ``` cd Desktop/folder-name ``` [যদি আপনার ফোল্ডারটির নাম archieves হয় তবে archieves লিখুন] এরপর লিখুন- ``` sudo dpkg -i *.deb ``` ব্যস এখন থেকে আপনি নতুন করে উবুন্টু/মিন্টে আপনার পুরনো সব সফটয়্যার ইনস্টলেশন করে ব্যবহার করতে পারবেন। --- # উবুন্টু বা মিন্টে ইনস্টল করুন .sh ফাইল > উবুন্টু এবং লিনাক্স মিন্ট অপারেটিং সিস্টেমে .sh ফাইল ইনস্টল করার পদ্ধতি। Published: 2011-08-29 URL: https://milon.im/post/install-sh-file-in-ubuntu-and-linux-mint.md অনেকেই উবুন্টু বা লিনাক্স মিন্টে `.sh` এক্সটেনশনের ফাইল ইনস্টল করতে ঝামেলার সম্মুখীন হয়েছেন। এটা আসলে খুবই সোজা। প্রথমে যে ফাইলটি থেকে সফটয়্যার ইনস্টল করবেন তা ফাইল সিস্টেমের কোন ফোল্ডারে রাখুন। মনে করি আমরা ফাইলটি ডেস্কটপে রাখলাম। এবার `start menu → Accessories → Terminal` থেকে টারমিনাল ওপেন করুন। এবার যে ফোল্ডারে ফাইলটি কপি করেছেন কারেন্ট ডিরেক্টরি পরিবর্তন করে সেখানে নিন। ডেস্কটপের জন্য লিখুন- ``` cd Desktop ``` এবার টারমিনালে নিচের কমান্ডটি লিখুন- ``` sudo sh ./name_of_file.sh ``` এবারে রুট পাসওয়ার্ড দিন। ব্যস হয়ে গেল আপনার .sh ফাইল থেকে সফটয়্যার ইনস্টলেশন। --- # সার্চিং এ্যালগরিদম (Searching algorithm) > Comparison between different searching algorithm. Published: 2011-06-17 URL: https://milon.im/post/searching-algorithm.md সার্চিং প্রোগ্রামিং এর ক্ষেত্রে একটি অত্যন্ত গুরুত্বপূর্ণ বিষয়। সিংহভাগ প্রোগ্রামের ক্ষেত্রেই কোন না কোন সার্চ আমাদের করতে হয়। সার্চিংয়ের ক্ষেত্রে লিনিয়ার সার্চ, বাইনারী সার্চ, ব্রেথ ফার্স্ট সার্চ(BFS), ডেপথ ফার্স্ট সার্চ(DFS) ইত্যাদি জনপ্রিয় এ্যালগরিদম। তবে BFS এবং DFS গ্রাফের সাথে সম্পর্কিত বলে আজকে এ বিষয়ে আলোচনা করব না। **লিনিয়ার সার্চঃ** লিনিয়ার সার্চ হল সবচেয়ে সহজ এবং সর্বাধিক ব্যবহৃত সার্চিং এ্যালগরিদম। এই এ্যালগরিদমের ক্ষেত্রে একসারি তথ্যের(ডাটা) মধ্য থেকে কাঙ্খিত তথ্যটি খুজে পাওয়ার জন্য একটি একটি করে সবগুলো ডাটা খুঁজে দেখা। যদি কাঙ্খিত ডাটাটি খুঁজে পাওয়া যায় তবে খোঁজা বন্ধ করে দেয়া হয়। সুবিধাঃ - কোড করা অনেক সহজ। - ডাটা যে অবস্থাতেই থাক না কেন খুঁজে পাওয়া সম্ভব। - অল্প সংখ্যক ডাটা থেকে কাঙ্খিত ডাটা খোঁজার জন্য অত্যন্ত উপযোগী। অসুবিধাঃ - তথ্য খুঁজে পেতে অনেক বেশি সময় লাগে। - অধিক পরিমানে তথ্যের মধ্য থেকে খোঁজার জন্য উপযোগী নয়। C++ প্রোগ্রামিং ভাষায় সোর্স কোডঃ ```cpp //Linear search #include using namespace std; int linear_search(int *a,int size, int key){ for(int i=0;i>n; int arr[n]; cout<<"Enter "<>arr[i]; cout<<"Enter the searching number: "; cin>>key; int res = linear_search(arr, n, key); if(res==0) cout<<"Key not found."< #include using namespace std; int binary_search(int a[], int size, int key) { int beg = 0, end = size-1; int mid = (beg+end)/2; while(beg<=end){ if(key>n; int arr[n]; cout<<"Enter "<>arr[i]; sort(arr, arr+n); cout<<"Sorted elements are:"<>key; int res = binary_search(arr, n, key); if(res==0) cout<<"Key not found."<a[j]){ int temp = a[i]; a[i] = a[j]; a[j] = temp; } } } } public static void main(String args[]) { Scanner input = new Scanner(System.in); System.out.println("Binary Search"); System.out.print("Enter the number of element in array: "); int n = input.nextInt(); int arr[] = new int[n]; System.out.print("Enter " + n + " numbers: "); for(int i=0;i মাভাবিপ্রবি ঘটনায় জাফর ইকবালের লেখা ও প্রশাসনের প্রতিক্রিয়া নিয়ে মন্তব্য। Published: 2011-05-30 URL: https://milon.im/post/opnion-of-professor-zafor-ikbal-about-mbstu-incident.md আপনারা পাবলিক বিশ্ববিদ্যালয়ের শিক্ষক, ছাত্র-ছাত্রীরা ক্লাস করলেও আপনারা বেতন পাবেন, না করলেও পাবেন। এ কারনে ৩০০ ছাত্রের ভবিষ্যত নিয়ে আপনাদের কোন মাথাব্যাথা নেই। কেন তারা এই আন্দোলন করছে, তা কি ভেবে দেখেছেন? যদি সিলেবাসের ১০-১৫% পরিবর্তন করে শিক্ষার্থীদের একটি যুগোপযোগী আধুনিক ডিগ্রি দেয়া যায়, তাহলে সে যৌক্তিক দাবী তারা করতেই পারে। এ কারনে তাদের নামে বহিষ্কারাদেশ, মধ্যযুগীয় কায়দায় পুলিশি নির্যাতন, গ্রেফতার করতে হবে কেন? ছাত্রদের কি কি কর্মসূচী ছিল তা বিশ্ববিদ্যালয়ের সবাই জানেন, এই কারনে তাদের বিরূদ্ধে চুরির মামলা দিতে আপনাদের বিবেকে বাধল না। আপনারা কি আপনাদের ছাত্রদের চোর বানাবার শিক্ষা দিচ্ছেন? জাফর ইকবাল স্যারের লেখার ব্যাপারে আপনারা [প্রতিক্রিয়া](http://www.prothom-alo.com/detail/date/2011-05-30/news/158201)য় বলেছেন, > ২৫ মে প্রথম আলোয় [সাদাসিধে কথা](http://www.prothom-alo.com/detail/date/2011-05-25/news/156889)য় 'ভাসানী বিশ্ববিদ্যালয় এবং আমরণ অনশন' শিরোনামের লেখায় শ্রদ্ধেয় মুহম্মদ জাফর ইকবাল মাওলানা ভাসানী বিজ্ঞান ও প্রযুক্তি বিশ্ববিদ্যালয় কর্তৃপক্ষ ও শিক্ষকদের সঙ্গে ছাত্রছাত্রীদের সম্পর্কের যে মেরুকরণ করেছেন, তার সঙ্গে আমরা দ্বিমত পোষণ করছি। জাফর স্যারের ব্যাপারে নতুন করে বলার কিছু নেই, আমরা সবাই তার ব্যাপারে জানি। জাফর স্যার ন্যায়ের পক্ষে কথা বলেছেন, কিন্তু তা আপনাদের বিপক্ষে গেছে। তাই বলেই তার কথা বিরোধিতা করতে হবে? আপনারা আপনাদের স্বপক্ষে জোরালো যুক্তি দিতে পারেন নি। ছাত্র শিক্ষকের সম্পর্কের মেরুকরন তো আপনারাই করছেন। তাদের নামে মিথ্যা মামলা দিচ্ছেন। একজন বিশ্ববিদ্যালয়ের ছাত্রকে কেন ডিগ্রি পরিবর্তন করার দাবীর অপরাধে জেলে রাত কাটাতে হবে? ফুড সহ অন্যান্য ডিপার্টমেন্টের ছেলেদের কেন মেস থেকে পুলিশ ধরে নিয়ে যাবে? এসকল প্রশ্নের উত্তর আপনারা কার কাছে দেবেন? তাদের বিরুদ্ধে আপনারা যে সব অন্যায় আচরন করেছেন তার বর্ণনা দিতে গেলে মহাকাব্য হয়ে যাবে। আগ্রহীরা চাইলে ঠিকানায় বিস্তারিত দেখতে পারেন। এ তো গেল ফুড ডিপার্টমেন্টের কথা। এই বিষয় নিয়ে বিশ্ববিদ্যালয় প্রশাসন অন্যান্য ডিপার্টমেন্টের ছেলেদের সাথেও অন্যায় আচরন করেছে। তাদের এ সমস্যার যাতে দ্রুত সমাধান হয় এজন্য মানববন্ধন করতে চাইলে বিশ্ববিদ্যালয়ের প্রক্টর আমাদের বলেন, > আপনারা যদি ফুডের ব্যাপারে কোন স্টেপ নেন, তাহলে আমি বিশ্ববিদ্যালয় বন্ধ করে দেব। এতে আপনাদেরই ক্ষতি। আমার কিছুই হবে না। বাংলাদেশের কোন বিশ্ববিদ্যালয় মানববন্ধন করার কারনে বন্ধ হয়ে গেছে আমার জানা নেই। বিশ্ববিদ্যালয় প্রশাসন তার অযোগ্যতা ঢাকার জন্য বহিষ্কারাদেশ দিয়েই যাচ্ছে। কোন ছাত্র কিছু বলতে চাইলে প্রথমেই তাকে বহিষ্কারের হুমকি দিয়ে বলা হয়- 'তোমার আইডি কত?' ছাত্ররা আপনাদের বিরুদ্ধে কোন কথা বললেই আপনারা তাদের বিরুদ্ধে বিভিন্ন ধরনের অনৈতিক পদক্ষেপ নেন। মাওলানা ভাসানী বিজ্ঞান ও প্রযুক্তি বিশ্ববিদ্যালয়ের ১৭০০ ছাত্রের মধ্যে ১ বছরে ৫২ জনের বহিষ্কার। বাংলাদেশের আর কোন বিশ্ববিদ্যালয়ে এ রেকর্ড আছে কিনা আমার জানা নেই। এই নোটটার জন্য আমার উপর বহিষ্কারাদেশ চলে এসে কিনা তার নিশ্চয়তা নেই।আমি অন্য ডিপার্টমেন্টের ছাত্র, আমার এ বিষয় নিয়ে কথা বললে হয়ত সমস্যা হতে পারে, তবুও বিড়ালের গলায় কাউকে না কাউকে ঘণ্টা বাঁধতেই হবে। ছাত্ররা নানা ভুল ত্রুটি করেছে। আপনারা সেসব কথা মিডিয়ার সামনে জোড় গলায় বলতে পারেন, কিন্তু আপনাদের অযোগ্যতার কথা কি আপনারা একবারও স্বীকার করেছেন? একবার ভাবুন তো ঐ মায়ের কথা, যে তার সন্তানকে বিশ্ববিদ্যালয়ে পাঠিয়েছে পড়াশুনা করার জন্য, কিন্তু সন্তান শিক্ষকদের করা মিথ্যা মামলায় চুরির দায়ে হাজতে রাত কাটাচ্ছে। তার জায়গায় নিজেকে একবার কল্পনা করুন। বিবেকের কাছে কি জবাব দেবেন? ছাত্ররা অন্যায়ের বিরুদ্ধে প্রতিবাদ করতে ভয় পায়। আপনারা তাদের সেই ক্ষমতাটুকুও কেড়ে নিয়েছেন। ছাত্রদের প্রতি আমার আহ্বান, যেখানে অন্যায়ের বিরুদ্ধে কিছু করার থাকে না সেখানে তাকে নাকি ঘৃণা করতে হয়। আমরা তাদের বিরুদ্ধে কিছু করতে না পারি, তাদেরকে অন্তত সমর্থন না দেই, ঘৃণা করতে শিখি। আমারতো মনে হয় বিশ্ববিদ্যালয় প্রশাসনের বিবেক না থাকলেও আমাদের আছে। আমরা বিবেকের এ দায় এড়াব কিভাবে? --- # মৌলিক সংখ্যা (Prime number) > Implement and optimize prime number generation algorithm. Published: 2011-05-25 URL: https://milon.im/post/prime-number.md Prime number বা মৌলিক সংখ্যা হচ্ছে সে সব সংখ্যা যার ১ এবং ঐ সংখ্যা ছাড়া আর কোন উৎপাদক নেই। অর্থাৎ ঐ সংখ্যাটি ১ এবং ঐ সংখ্যা ছাড়া নিঃশেষে বিভাজ্য নয়। প্রোগ্রামারদের কাছে মৌলিক সংখ্যা খুব পছন্দের একটা বিষয়। যে কোন ধরনেন প্রোগ্রামিং প্রতিযোগিতায় সাধারনত অন্তত একটা সমস্যা থাকে প্রাইম নাম্বার থেকে। প্রাইম নাম্বার বের করার প্রোগ্রামটি খুব সহজেই লিখে ফেলা যায়। ```cpp //Prime number check //Author: Milon #include using namespace std; bool isPrime(int num){ if(num<2) return false; for(int i=2;i>n && n){ if(isPrime(n)) cout< #include using namespace std; #define max 19000000 bool prime[max+1]; void sieve() { long int i,j; for(i=2;i<=max;i++) prime[i]=true; for(i=2;i*i<=max;){ for(j=2*i;j<=max;j+=i){ prime[j]=false; } i++; while(!prime[i]) i++; } } int main() { sieve(); long int n; while(scanf("%ld",&n)==1){ if(prime[n]==true) printf("prime\n"); else printf("not prime\n"); } return 0; } ``` --- # ডাটা স্ট্রাকচারঃ Adjacency List > How to implement adjacency list. Published: 2011-05-24 URL: https://milon.im/post/data-structure-adjacency-list.md গ্রাফের নোডের সংখ্যা যদি অনেক বেশী হয়, তখন Adjacency Matrix ব্যবহার করে গ্রাফ তৈরী করা অসুবিধাজনক। সেক্ষেত্রে Linked List ব্যবহার করে গ্রাফ তৈরী করা হয়। গ্রাফের এই ধরনের উপস্থাপনাকে Adjacency List বলে। ```cpp //Adjacency list //Author: Milon #include #include using namespace std; struct list{ int val; struct list *next; }; struct list head[6]; int main(){ list *ptr,*newnode; int data[14][2] = {{1,2},{2,1},{1,5},{5,1},{2,3},{3,2},{2,4}, {4,2},{3,4},{4,3},{3,5},{5,3},{4,5},{5,4}}; //Adjacency list creation cout<<"The adjacent list of the graph : "< "; ptr=&(head[i]); for(int j=0;j<14;j++){ if(data[j][0]==i){ newnode=new list(); newnode->val=data[j][1]; newnode->next=NULL; while(ptr!=NULL) ptr=ptr->next; ptr=newnode; cout<<"["<val<<"] "; } } cout< How to implement directed graph. Published: 2011-05-24 URL: https://milon.im/post/data-structure-directed-graph.md Directed Graph আর Undirected Graph এর মধ্যে বিশেষ তফাৎ নেই। শুধুমাত্র পেছনে আসার রাস্তাটা বন্ধ করে দিলেই Undirected Graph টা Directed হয়ে যাবে। ```cpp //Directed graph //Author: Milon #include #include using namespace std; int main(){ int n; cout<<"Enter the number of nodes: "; cin>>n; bool list[n][n]; //Initialize for(int i=0;i>a>>b; if(a==0 && b==0) break; if(a>n || b>n || a<=0 || b<=0) cout<<"Invalid input"< How to implement two way linked list. Published: 2011-05-24 URL: https://milon.im/post/data-structure-two-way-linked-list.md জাভাতে C বা C++ এর মত পয়েন্টার নাই। পয়েন্টারের কাজ জাভাতে reference এর মাধ্যমে করা হয়। সাধারন বা ওয়ান ওয়ে লিঙ্ক লিস্টের মত খুব সহজেই জাভা প্রোগ্রামিং ভাষা ব্যবহার করে টু ওয়ে লিঙ্ক লিস্ট তৈরী করা যায়। `TwoWayLinkedList.java` ```java //Two Way Linked List //Author: Milon import java.util.NoSuchElementException; //Node class class Node{ //Instance variable private Object data; private Node nextNode; private Node previousNode; //Constructor public Node(){ data = null; nextNode = null; previousNode = null; } public Node(Object item, Node next, Node previous){ data = item; nextNode = next; previousNode = previous; } //Set methods public void setData(Object item){ data = item; } public void setNextNode(Node next){ nextNode = next; } public void setPreviousNode(Node previous){ previousNode = previous; } //Get methods public Object getData(){ return data; } public Node getNextNode(){ return nextNode; } public Node getPreviousNode(){ return previousNode; } //Overloaded toString() method public String toString(){ return ("" + data); } } //Two Way Linked List class public class TwoWayLinkedList{ //Instance variable private int size; private Node head; private Node tail; //Constructor public TwoWayLinkedList(){ head = tail = null; size = 0; } //Returns is the list empty public boolean isEmpty(){ return head == null; } //Returns the size of list public int size(){ return size; } //Insert element at first position public void addFirst(Object item){ if(isEmpty()){ head = tail = new Node(item, head, tail); ++size; return; } Node current = new Node(item, head, null); head.setPreviousNode(current); head = current; ++size; } //Insert an element at last public void addLast(Object item){ if(isEmpty()){ addFirst(item); return; } Node current = new Node(item, null, tail); tail.setNextNode(current); tail = current; ++size; } //Show the first item public Object showFirst(){ if(!isEmpty()) return head.getData(); else{ System.out.println("LinkedList is empty."); //throw new NoSuchElementException(); return null; } } //Show the last item public Object showLast(){ if(!isEmpty()) return tail.getData(); else{ System.out.println("LinkedList is empty."); //throw new NoSuchElementException(); return null; } } //Remove the first element public Object removeFirst(){ if(head.getNextNode() == null){ Node current = head; head = null; tail = null; --size; return current.getData(); } if(!isEmpty()){ Node current = head; head = head.getNextNode(); head.setPreviousNode(null); --size; return current.getData(); } else{ System.out.println("LinkedList is empty."); //throw new NoSuchElementException(); return null; } } //Remove the last element public Object removeLast(){ if(isEmpty()){ System.out.println("LinkedList is empty."); //throw new NoSuchElementException(); return null; } if(head.getNextNode() == null){ --size; return removeFirst(); } Node current = tail; tail = tail.getPreviousNode(); tail.setNextNode(null); --size; return current.getData(); } //Check does the item exists in the list public boolean contains(Object item){ Node current = head; while(current.getNextNode() != null){ if(item.equals(current.getData())) return true; else current = current.getNextNode(); } return false; } //Traversing the list from front public String frontTraverse(){ String str = "[ "; if(head != null){ str += head.getData(); Node current = head.getNextNode(); while(current.getNextNode() != null){ str += ", " + current.getData(); current = current.getNextNode(); } str += ", " + current.getData(); } str += " ]"; return str; } //Traversing the list from rear public String rearTraverse(){ String str = "[ "; if(tail != null){ str += tail.getData(); Node current = tail.getPreviousNode(); while(current.getPreviousNode() != null){ str += ", " + current.getData(); current = current.getPreviousNode(); } str += ", " + current.getData(); } str += " ]"; return str; } } ``` `TwoWayLinkedListImplement.java` ```java //Two Way Linked List Implementation class //Author: Milon import java.util.Scanner; import java.util.Random; public class TwoWayLinkedListImplement{ public static void main(String args[]){ TwoWayLinkedList list = new TwoWayLinkedList(); Scanner input = new Scanner(System.in); Random rand = new Random(); System.out.print("How many item do you want to insert first: "); int n = input.nextInt(); for(int i=0;i How to implement weighted graph. Published: 2011-05-24 URL: https://milon.im/post/data-structure-weighted-graph.md যে গ্রাফের প্রত্যেকটা এজের(edge) একটা Weight বা মান দেয়া থাকে তাকে Weighted Graph বলে। Weighted graph তৈরীর কৌশল হল- ```cpp //Weighted graph //Author: Milon #include #include using namespace std; int main(){ int n; cout<<"Enter the number of nodes: "; cin>>n; int list[n][n]; //Initialize for(int i=0;iend_node< >weight)"<>a>>b>>c; if(a==0 && b==0 && c==0) break; if(a>n || b>n || a<=0 || b<=0) cout<<"Invalid input"< How to implement undirected graph. Published: 2011-05-23 URL: https://milon.im/post/data-structure-undirected-graph.md Directed Graph আর Undirected Graph এর মধ্যে বিশেষ তফাৎ নেই। শুধুমাত্র পেছনে আসার রাস্তাটা বন্ধ করে দিলেই Undirected Graph টা Directed হয়ে যাবে। ```cpp //Directed graph //Author: Milon #include #include using namespace std; int main(){ int n; cout<<"Enter the number of nodes: "; cin>>n; bool list[n][n]; //Initialize for(int i=0;i>a>>b; if(a==0 && b==0) break; if(a>n || b>n || a<=0 || b<=0) cout<<"Invalid input"< How to implement list. Published: 2011-05-22 URL: https://milon.im/post/data-structure-linked-list.md লিঙ্ক লিস্ট অত্যন্ত গুরুত্বপূর্ণ ডাটা স্ট্রাকচার। বহু ক্ষেত্রে লিঙ্ক লিস্টের ব্যবহার হয়ে থাকে। ডায়নামিক মেমোরী এ্যালোকেশনের ক্ষেত্রে লিঙ্ক লিস্টই হচ্ছে সবচেয়ে শক্তিশালী উপাদান। অন্যান্য ডাটা স্ট্রাকচার যেমন- স্ট্যাক, কিউ, ট্রি, গ্রাফ ইত্যাদি তৈরী করতেও লিঙ্ক লিস্ট ব্যবহার করা হয়। C++ কোড: ```cpp //Linked list operations //Author: Milon #include #include #include //#include void insert_first(); void insert_last(); void insert_before(); void insert_after(); void search_list(); void delete_node(); void show_list(); struct student{ char name[25]; char roll[8]; char dept[4]; char semester[10]; struct student *next; } *start=NULL; void main(){ int d=0; char choice; do{ //clrscr(); printf("This program is for Linked List operations.\n\n"); printf("# Insert at (F)irst position.\n"); printf("# Insert at (L)ast position.\n"); printf("# Insert (B)efore node.\n"); printf("# Insert (A)fter node.\n"); printf("# (S)earch in a list.\n"); printf("# (R)emove a node from list.\n"); printf("# (D)isplay all nodes of list.\n"); printf("# (E)xit\n\n\n"); printf("Enter your choice: "); choice=getchar(); switch(choice){ case 'F': case 'f': insert_first(); break; case 'L': case 'l': insert_last(); break; case 'B': case 'b': insert_before(); break; case 'A': case 'a': insert_after(); break; case 'S': case 's': search_list(); break; case 'R': case 'r': delete_node(); break; case 'D': case 'd': show_list(); break; case 'E': case 'e': d=1; break; default: printf("\nInvalid input."); break; } }while(d==0); } void insert_first(){ struct student *data; data=(struct student*)malloc(sizeof(struct student)); printf("\nEnter your name: "); gets(data->name); printf("\nEnter your roll: "); gets(data->roll); printf("\nEnter your department: "); gets(data->dept); printf("\nEnter your semester: "); gets(data->semester); data->next=NULL; if(start==NULL) start=data; else{ data->next=start; start=data; } printf("\nItem successfully inserted."); //getch(); } void insert_last(){ struct student *data,*ptr; data=(struct student*)malloc(sizeof(struct student)); printf("\nEnter your name: "); gets(data->name); printf("\nEnter your roll: "); gets(data->roll); printf("\nEnter your department: "); gets(data->dept); printf("\nEnter your semester: "); gets(data->semester); data->next=NULL; if(start==NULL) start=data; else{ ptr=start; while(ptr->next!=NULL) ptr=ptr->next; ptr->next=data; } printf("\nItem successfully inserted."); //getch(); } void insert_before(){ char roll[8]; struct student *data,*prev,*ptr; printf("\nEnter the student roll before which you want to insert: "); gets(roll); ptr=start; while(strcmp(roll,ptr->roll)!=0&&ptr!=NULL) ptr=ptr->next; if(ptr==NULL){ printf("\Item not found."); //getch(); return; } data=(struct student*)malloc(sizeof(struct student)); printf("\nEnter your name: "); gets(data->name); printf("\nEnter your roll: "); gets(data->roll); printf("\nEnter your department: "); gets(data->dept); printf("\nEnter your semester: "); gets(data->semester); data->next=NULL; ptr=start; if(strcmp(roll,ptr->roll)==0){ ptr->next=start; start=ptr; } else{ ptr=ptr->next; prev=start; while(strcmp(roll,ptr->roll)!=0){ ptr=ptr->next; prev=prev->next; } } data->next=ptr; prev->next=data; printf("\nItem successfully Inserted."); //getch(); } void insert_after(){ char roll[8]; struct student *data,*ptr; printf("\nEnter the student roll before which you want to insert: "); gets(roll); ptr=start; while(strcmp(roll,ptr->roll)!=0&&ptr!=NULL) ptr=ptr->next; if(ptr==NULL){ printf("\Item not found."); //getch(); return; } data=(struct student*)malloc(sizeof(struct student)); printf("\nEnter your name: "); gets(data->name); printf("\nEnter your roll: "); gets(data->roll); printf("\nEnter your department: "); gets(data->dept); printf("\nEnter your semester: "); gets(data->semester); data->next=NULL; ptr=start; while(strcmp(roll,ptr->roll)!=0) ptr=ptr->next; data->next=ptr->next; ptr->next=data; printf("\nItem successfully inserted."); //getch(); } void search_list(){ char roll[8]; struct student *ptr; printf("\nEnter the student roll you want to search: "); gets(roll); ptr=start; while(strcmp(roll,ptr->roll)!=0&&ptr->next!=NULL) ptr=ptr->next; if(ptr->next==NULL) printf("\nNo match found."); else{ printf("\nItem found.\n"); printf("%28s %10s %5s %12s",ptr->name,ptr->roll,ptr->dept,ptr->semester); } //getch(); } void delete_node(){ char roll[8]; struct student *ptr,*prev; printf("\nEnter the student roll you want to search: "); gets(roll); ptr=start; if(strcmp(ptr->roll,roll)==0) start=ptr->next; else{ ptr=ptr->next; prev=start; while(strcmp(roll,ptr->roll)!=0&&ptr->next!=NULL){ ptr=ptr->next; prev=prev->next; } if(ptr->next==NULL) printf("No match found."); else prev->next=ptr->next; } printf("\nNode is successfully deleted."); //getch(); } void show_list(){ int c=0; struct student *ptr; if(start==NULL) printf("List is empty."); else{ ptr=start; while(ptr!=NULL){ printf("\n%3d.%25s%10s%5s%12s",++c,ptr->name,ptr->roll,ptr->dept,ptr->semester); ptr=ptr->next; } } //getch(); } ``` Java কোড: `LinkedList.java` ```java //Linked List class //Author: Milon import java.util.Scanner; import java.util.Iterator; import java.util.NoSuchElementException; //Node class class Node{ //Instance variable private Object data; private Node nextNode; //Constructor public Node(){ data = null; nextNode = null; } public Node(Object item, Node next){ data = item; nextNode = next; } //Set methods public void setData(Object item){ data = item; } public void setNextNode(Node next){ nextNode = next; } //Get methods public Object getData(){ return data; } public Node getNextNode(){ return nextNode; } //Overloaded toString() method public String toString(){ return ("" + data); } } //LinkedList class public class LinkedList{ //Instance variable protected Node head; private int size; //Constructor public LinkedList(){ head = null; size = 0; } //Returns is the list empty public boolean isEmpty(){ return head == null; } //Returns the size public int size(){ return size; } //Insert an element at first position public void addFirst(Object item){ head = new Node(item, head); ++size; } //Insert an element at last position public void addLast(Object item){ if(isEmpty()){ addFirst(item); return; } Node current = head; while(current.getNextNode() != null) current = current.getNextNode(); Node temp = new Node(item, current.getNextNode()); current.setNextNode(temp); ++size; } //Show the first item public Object showFirst(){ if(head != null) return head.getData(); else{ System.out.println("LinkedList is empty."); //throw new NoSuchElementException(); return null; } } //Show the last item public Object showLast(){ if(head == null){ System.out.println("LinkedList is empty."); //throw new NoSuchElementException(); return null; } else{ Node current = head; while(current.getNextNode() != null) current = current.getNextNode(); return current.getData(); } } //Show the nth element public Object peek(int position){ Node current = head; for(int i=0;i How to implement queue. Published: 2011-05-22 URL: https://milon.im/post/data-structure-queue.md কিউ হচ্ছে First In First Out(FIFO) ডাটা স্ট্রাকচার। অর্থাৎ যে আইটেমটা সবার প্রথমে ইনসার্ট করা হয় সেটাই সবার প্রথমে ডিলিট করা হয়। অ্যারে বা লিঙ্ক লিস্ট ব্যবহার করে কিউ তৈরী করা যায়। C++ কোড: ```cpp //Queue using array //Author: Milon #include using namespace std; #define MAX 5 // MAXIMUM CONTENTS IN QUEUE class queue{ private: int t[MAX]; int add; // Addition End int del; // Deletion End public: queue(){ del=-1; add=-1; } void delet(){ int tmp; if(del==-1){ cout<<"Queue is Empty"< How to implement stack. Published: 2011-05-22 URL: https://milon.im/post/data-structure-stack.md স্ট্যাক হচ্ছে Last In First Out(LIFO) ডাটা স্ট্রাকচার। অর্থাৎ যে আইটেমটা সবার শেষে ইনসার্ট করা হয় সেটাই সবার প্রথমে ডিলিট করা হয়। অ্যারে বা লিঙ্ক লিস্ট ব্যবহার করে স্ট্যাক তৈরী করা যায়। C++কোড: ```cpp //Stack using array //Author: Milon #include //#include #define max 50 void push(); void pop(); void display(); int top=0; int stack[max]; void main(){ int c=0; char ch; do{ //clrscr(); printf("This program is for Push & Pop operation.\n"); printf("Enter your choice:\n"); printf("# (P)ush operatino.\n"); printf("# Pop (O)peration.\n"); printf("# (D)isplay stack.\n"); printf("# (E)xit.\n\n"); printf("Enter your choice: "); ch=getchar(); switch(ch){ case 'P': case 'p': push(); break; case 'O': case 'o': pop(); break; case 'D': case 'd': display(); break; case 'E': case 'e': c=1; break; default: printf("\nInvalid input."); //getch(); break; } }while(c!=1); } void push(){ int data; if(top==max){ printf("\nStack is overflow."); //getch(); return; } printf("\nEnter data for Push: "); scanf("%d",&data); top=top+1; stack[top]=data; printf("\nPush operation complete successfully."); //getch(); } void pop(){ if(top==0){ printf("\nStack is underflow."); //getch(); return; } printf("\nData %d is deleted.",stack[top]); top=top-1; printf("\nPop operation complete successfully."); //getch(); } void display(){ if(top==0){ printf("\nStack is empty."); //getch(); return; } printf("\nStack: "); for(int i=1;i<=top;i++) printf("%d -->",stack[i]); //getch(); } ``` Java কোড: `Stack.java` ```java //Stack //Author: Milon import java.util.NoSuchElementException; //Node class class Node{ //Instance variable protected Object data; private Node nextNode; //Constructor public Node(){ data = null; nextNode = null; } public Node(Object item, Node next){ data = item; nextNode = next; } //Set methods public void setData(int item){ data = item; } public void setNextNode(Node next){ nextNode = next; } //Get methods public Object getData(){ return data; } public Node getNextNode(){ return nextNode; } //Overloaded toString method public String toString(){ return "" + data; } } //Stack class public class Stack{ //Instance variable private Node top; private int size; //Constructor public Stack(){ top = null; size = 0; } //Returns is the stack empty public boolean isEmpty(){ return top == null; } //Returns size of the stack public int size(){ return size; } //Push method public void push(Object item){ top = new Node(item, top); ++size; } //Pop method public Object pop(){ if(!isEmpty()){ Node current = top; top = top.getNextNode(); --size; return current.getData(); } else{ System.out.println("Stack underflow."); //throw new NoSuchElementException(); return null; } } //Peek method public Object peek(){ if(!isEmpty()) return top.getData(); else{ System.out.println("Stack underflow."); //throw new NoSuchElementException(); return null; } } //Overloaded toString method to show the entire list public String toString(){ String str = "[ "; if(top != null){ str += top.getData(); Node current = top.getNextNode(); while(current.getNextNode() != null){ str += ", " + current.getData(); current = current.getNextNode(); } str += ", " + current.getData(); } str += " ]"; return str; } } ``` `StackImplement.java` ```java //Stack Implementation class //Author: Milon import java.util.Scanner; import java.util.Random; public class StackImplement{ public static void main(String args[]){ Scanner input = new Scanner(System.in); Random rand = new Random(); Stack stack = new Stack(); System.out.print("How many number of element do you want: "); int n = input.nextInt(); for(int i=0;i How to connect MySQL with Java. Published: 2011-05-21 URL: https://milon.im/post/connect-mysql-with-java.md জাভা বর্তমান পৃথিবীর অত্যন্ত জনপ্রিয় একটা প্রোগ্রামিং ভাষা। যে কোন ধরনের অ্যাপ্লিকেশন ডেভেলপ করতে জাভার কোন জুড়ি নেই। আর বর্তমানের অধিকাংশ সফটয়্যারেই ডাটাবেজ ব্যবহার করা হয়। জাভার সাথে ডাটাবেজের কিভাবে সংযোগ দিতে হয় তা এই পোষ্টের মাধ্যমে দেখান হল। ডাটাবেজে বিভিন্ন ধরনের অপারেশন চালানোর জন্য জাভার Statement class(কমেন্টের মধ্যে) এবং অত্যাধুনিক PreparedStatement class ব্যবহার করা হয়েছে। জাভাতে ডাটাবেজের কোন পরিবর্তন আনার জন্য executeUpdate() এবং কোন তথ্য অনুসন্ধানের জন্য executeQuery() মেথড ব্যবহার করা হয়। ```java //Mysql connection //Author: Milon //import java.sql.*; import java.sql.Connection; import java.sql.Statement; import java.sql.PreparedStatement; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; public class MysqlConnection{ private static String driver = "com.mysql.jdbc.Driver"; private static String connection = "jdbc:mysql://localhost:3306/milon"; //'milon' is your database name private static String user = "root"; //'root' is username private static String password = "pass"; //'pass' is password private static Connection con = null; private static Statement state = null; private static ResultSet result; private static PreparedStatement pstate; public static void main(String args[])/* throws Exception*/{ mysqlConnect(); insertData("s6s","milon","dgh","ghjgh"); deleteData("sd"); countRow("dictionary"); updateData("ss", "suru"); showData("surayea"); closeConnection(); } public static void mysqlConnect(){ try{ Class.forName(driver); con = DriverManager.getConnection(connection, user, password); System.out.println("Successfully connected to database."); } catch(ClassNotFoundException e){ System.err.println("Couldn't load driver."); } catch(SQLException e){ System.err.println("Couldn't connect to database."); } } public static void closeConnection(){ try{ if(!con.isClosed()){ con.close(); System.out.println("Database closed successfully."); } } catch(NullPointerException e){ System.err.println("Couldn't load driver."); } catch(SQLException e){ System.err.println("Couldn't close database."); } } public static void insertData(String word, String meaning, String synonyms, String antonyms){ try{ //using PreparedStatement pstate = con.prepareStatement("insert into dictionary(word, meaning, synonyms, antonyms)"+ "values(?,?,?,?)"); pstate.setString(1, word); pstate.setString(2, meaning); pstate.setString(3, synonyms); pstate.setString(4, antonyms); int value = pstate.executeUpdate(); //using Statement //state = con.createStatement(); //int value = state.executeUpdate("insert into dictionary(word, meaning, synonyms, antonyms)"+ // "values('"+word+"', '"+meaning+"', '"+synonyms+"', '"+antonyms+"')"); System.out.println("Query OK, 1 row insertedted."); } catch(SQLException e){ System.err.println("Query error."); } } public static void deleteData(String word){ try{ //using PreparedStatement pstate = con.prepareStatement("delete from dictionary where word = ?"); pstate.setString(1,"word"); int value = pstate.executeUpdate(); //using Statement //state = con.createStatement(); //int value = state.executeUpdate("delete from dictionary where word='"+word+"'"); System.out.println("Query OK, 1 row deleted."); } catch(SQLException e){ System.err.println("Query error."); } } public static void countRow(String table){ try{ result = state.executeQuery("SELECT COUNT(*) FROM "+table); result.next(); int rowcount = result.getInt(1); System.out.println("Number of rows: "+rowcount); } catch(SQLException e){ System.err.println("Query error."); } } public static void showData(String word){ try{ state = con.createStatement(); result = state.executeQuery("select * from dictionary where word='"+word+"'"); while(result.next()){ String word1 = result.getString("word"); String mean = result.getString("meaning"); String syno = result.getString("synonyms"); String anto = result.getString("antonyms"); System.out.println("Word: "+word1+" Meaning: "+mean+" Synonyms: "+syno+" Antonyms: "+anto); } } catch(SQLException e){ System.err.println("Query error."); } catch(NullPointerException e){ System.err.println("Element not found."); } } public static void updateData(String word, String meaning){ try{ //using Statement //state = con.createStatement(); //int value = state.executeUpdate("update dictionary set meaning='"+meaning+"' where word='"+word+"'"); //using PreparedStatement pstate = con.prepareStatement("update dictionary set meaning= ? whrere word = ?"); pstate.setString(1, meaning); pstate.setString(2, word); pstate.executeUpdate(); System.out.println("Query OK, 1 row updated."); } catch(SQLException e){ System.err.println("Query error."+e.getMessage()); } } } ``` --- # ভালবাসার জন্য > ভালবাসার জন্য কী করা যায়, আর কী করা যায় না — একটি কবিতা। Published: 2011-05-19 URL: https://milon.im/post/valobashar-jonno.md তোমার কি ভালবাসা চাই?
কোন ভালবাসা? কতটা, কত গভীরতার?
যা চাও সবই দিতে পারব আমি।
ভালবাসার জন্য তাজমহল আমি বানাতে পারব না ঠিকই
তবে আমার হৃদয়ে যে তাজমহল, তোমার জন্য
তা কি দেখে কখনো শেষ করতে পারবে?
সম্রাট এডওয়ার্ডের মত কখনোই আমি সিংহাসন ছেড়ে দেব না
বরং তোমার জন্য তার একপাশে জায়গা করে দেব। দান্তের মত হয়ত ডিভাইন কমেডি লিখে দিতে পারব না
অথবা কবি ইকবালের মত প্রেমের কোন মহাকাব্য
তবে হৃদয় নিঙরানো অনুভূতি ঠিকই বোঝাতে পারব তোমাকে
তোমাকে কোটি কোটি টাকা হয়ত দিতে পারব না ঠিকই
তবে কখনো তোমাকে কোন অভাবে রাখব না
অন্তত ভালবাসার অভাব তো নয়ই,
তোমার জন্য মায়ের শাসন, বাবার রক্তচক্ষু উপেক্ষা করতে পারব
এক কাপড়ে রাস্তায় এসে দাড়াতে পারব
পুরোটা মেঘনাদবধ মুখস্ত শোনাতে পারব
আশি পৃষ্ঠার একটা রোমান্টিক প্রেমপত্র লিখে দিতে পারব
ক্লাস ফাঁকি দিয়ে ঘন্টার পর ঘন্টা অপেক্ষা করতে পারব
তুমি যদি বল, হেরে গলায় তোমাকে গানও শোনাতে পারব
শীতের রাতে সাতরে পুকুর পাড়ি দিতে পারব
দু'পায়ে ভর করে টেকনাফ থেকে তেতুলিয়া ঘুরে আসতে পারব
ঘন্টার পর ঘন্টা অপলক তোমার দিকে তাকিয়ে থাকতে পারব
সারাজীবন তোমার অপেক্ষায় থাকতে পারব
ভালবাসার জন্য আমি কিন্তু অনেক কিছুই করতে পারব, করবোও
তবে ভালবাসাহীন কোন মানুষের জন্য, এক বিন্দুও নয়। ২৯.০৮.২০০৮
রাত ১১.০৬ --- # স্মৃতি-বিস্মৃতি > স্মৃতির ভয়ে ফেরারী হওয়ার কথা — একটি কবিতা। Published: 2011-05-18 URL: https://milon.im/post/smriti-bismriti.md একা থাকতে আমি বড্ড ভয় পাই
ভয় না পেয়ে উপায় আছে?
কিলিং স্কোয়াডের মত তোমার স্মৃতিগুলো
সারাক্ষন আমাকে তাড়া করে বেড়ায়।
পরিচিত সেই রাস্তা ধরে হাটলে
আজও মনে হয়, তুমি আসবে
পেছন থেকে এসে হাত বাড়িয়ে দেবে
এ ভয়েই তো সে রাস্তা ছেড়ে দিয়েছি আমি,
পরিচিত সেই গানের সুর কানে বাজলে
কিংবা পরিচিত সেই পারফিউমের ঘ্রান
আমাকে আবারো মনে করিয়ে দেয় তোমাকে
একা হতেই যে স্মৃতিগুলো ফিরে আসে
ভয় না পেয়ে উপায় আছে, বলো?
চকলেট খাওয়া তো ছেড়েই দিয়েছি
বৃষ্টিতেও ভিজতে পারি না
এখানেও যে স্মৃতিগুলো তাড়া করে বেড়ায়
বিশেষ কিছু দিন, বিশেষ কিছু মুহুর্ত
এমনকি মুঠোফোনটাও, তোমাকে মনে করিয়ে দেয়
তোমার স্মৃতিগুলোর ভয়ে ফেরারী না হয়ে উপায় আছে, বলো? তাই তো আমি পরিচিত সব কিছু ছাড়তে চাইছি
আমার জগৎকে ছোট করে ফেলেছি
তোমার স্মৃতিগুলো আমার চারদিকে একটা বৃত্ত তৈরী করেছে
বৃত্তটা ধীরে ধীরে ছোট হয়ে আসছে
একসময় এরাই আমার সামনে এসে দাড়াবে, আমার গলা চেপে ধরবে
আমি জানি, তখনো একটা অস্ফুট আর্তচিৎকারই বেরুবে আমার মুখ থেকে
আমি তোমাকে ভুলতে চাই। ২৮.০৮.২০০৮
সকাল ০৭.১৪ --- # তোমার কল্পনা এবং আমি > কল্পনার রাজপুত্র নয়, সাধারণ মানুষ হিসেবে ভালবাসার দাবি — একটি কবিতা। Published: 2011-05-17 URL: https://milon.im/post/tomar-kolpona-abong-ami.md তোমার কল্পনার মানুষটির মত কখনোই হতে পারব না আমি,
কিভাবে পারব বলো?
সে নিশ্চই ভাড়া নিয়ে রিক্সাওয়ালার সাথে দরাদরি করে না
কিংবা কাচাবাজারে সবজির দাম বেশি বলে বিক্রেতার সাথে তর্ক জুড়ে দেয় না
তোমার কল্পনার রাজপুত্র নিশ্চই ঘর্মক্লান্ত হয়ে বাড়ি ফেরে না
সে নিশ্চই বাসে ওঠার জন্য সহযাত্রী কে ধাক্কা দেয় না
আচ্ছা সে কি জ্বালানী তেলের মূল্যবৃদ্ধি নিয়ে চায়ের কাপে ঝড় তোলে?
নাকি সে তোমার কল্পনার মত সারাক্ষন তোমাকে নিয়েই মশগুল। সফেদ ভাতের প্লেটে চুল কেন? কিংবা তরকারিতে লবন কেন বেশি?
হাত খরচার টাকার জন্য সে কি মায়ের পিছন পিছন ঘুরঘুর করে?
মোড়ের টং দোকানওয়ালা নিশ্চই তাকে বাকি চেয়ে তাগাদা দেয় না।
সে নিশ্চই ছেড়া ফিতাওয়ালা স্লিপার নিয়ে মুচির কাছে যায় না। আমি তোমার কল্পনার মানুষ কিভাবে হবো বলো?
আমি তো আর দেখতে শেষের কবিতার অমিতের মত নই
হুমায়ূনের হিমু কিংবা মিসির আলীর অতিন্দ্রীয়তাও যে আমাকে স্পর্শ করে না
খুব সাধারন, আটপৌরে জীবন আমার
তবুও আমি, তোমার আমি হতে চাই
হতে চাই আমি সেই ভালবাসার জোড়ে যে ভালবাসা আজও পৃথিবীর কেউ পায় নি। তোমার স্বপ্নের সারথী আমি কি করে হবো বলো?
সে তো আর বন্ধুদের আড্ডায় পড়ে সময়জ্ঞান ভুলে যায় না আমি কি করবো বলো?
আমি যে মুঠোফোনে জীবনান্দের কবিতা আওড়াতে পারি না
মিষ্টি প্রেমপত্র কিংবা বাবার পকেট মেরে একগুচ্ছ গোলাপ
অথবা কিশোর ছেলেদের মত তোমার জন্য রোদে দাড়িয়ে থেকে জন্ডিস বাধানো
এর কোনোটাই যে আমাকে দিয়ে হবে না,
তোমাকে আকৃষ্ট করার মত কিছুই যে নেই
আমার তবুও আমি তোমার কাছাকাছি থাকতে চাই, হাত ধরতে চাই
আমি যে তোমাকে ভালবাসি, সত্যিই ভালবাসি এটুকুই কি যথেষ্ট নয়? ২৫.০৮.২০০৮
রাত ১০.৪৫ --- # একটি মানচিত্রের গল্প ও অফটপিকের কিছু কথা > একটি মানচিত্রের গল্প দিয়ে নৈতিকতা, বিশ্ববিদ্যালয় ও দেশ গড়ার দায় নিয়ে লেখা। Published: 2011-05-16 URL: https://milon.im/post/akti-manchitrer-golpo-abong-0fftopic-er-kichu-kotha.md একটা গল্প বলেই শুরু করি। একটা ৮-৯ বছরের বাচ্চা একটা কাগজের মানচিত্র নিয়ে খেলছে। খেলতে খেলতে সে মানচিত্রটা ছিড়ে ফেলেছে। তার বাবা এটা দেখে তো খুব রাগ করল। ছেলেটাকে বলল, তুমি মানচিত্রটি ছিড়লে কেন? এখন তোমাকে আধঘণ্টা সময় দিচ্ছি, তুমি যেভাবে পার মানচিত্রটা জোড়া দাও। ছেলে তো পড়ল মহা বিপাকে। আধঘণ্টা পর বাবা এসে দেখে ছেলেটা ঠিকই মানচিত্রটা জোড়া দিয়ে ফেলেছে। বাবা তো অবাক! বাবা জিজ্ঞেস করল, তুমি তো মানচিত্রটা চেনো না, তুমি এটা জোড়া দিলে কিভাবে? ছেলে বলে, বাবা, আমি মানচিত্র জোড়া দেই নি, মানচিত্রের পেছনে একটা মানুষের ছবি ছিল, আমি সেই ছবিটা জোড়া দিয়েছি, মানচিত্র এমনিতেই জোড়া লেগে গেছে। গল্প শেষ। এবার আমি আমার মূল টপিকে ফিরে আসি। অনেকেই বলে আমি তো চুনোপুঁটি, আমি দেশের কাজে কিভাবে লাগতে পারি। তাদের জন্যে উপরের গল্পটা। আমার কথা হচ্ছে তুমি নিজে নিজেকে গড়ে তোল, দেখবে দেশটা ঠিকই গড়ে উঠেছে। আমি বিশ্ববিদ্যালয়ে এসেছি নিজেকে একজন পূর্নাঙ্গ মানুষ হিসেবে গড়ে তোলার জন্য। আমি দিন-রাত পড়াশুনা করবো, একাডেমিকালি ভালো ফলাফল করবো, কিন্তু আমার ভিতরে মানবিক গুনাবলি পরিস্ফুটিত হবে না, তাহলে সে শিক্ষার আদৌ কি কোনো মূল্য আছে? মনিষী প্রমথ চৌধুরী বলেছেন- > শিক্ষার আসল উদ্দেশ্য হচ্ছে মূল্যবোধের পরিবর্তন। জ্ঞানের কথা একটু বেশিই হয়ে যাচ্ছে। আমি আমার কথায় ফিরে আসি। আমি শুধু পড়াশুনা করেই যাব, আর আমার চোখের সামনে দিয়ে অন্যায় হয়ে যাবে আর, আমি তার প্রতিবাদ করবো না তা হলে তো আমার পড়াশুনাই বৃথা। আমি পাবলিক বিশ্ববিদ্যালয়ে ভর্তি হয়ে শুধু ভুলই করিনি, আমি অপরাধ করেছি। সরকার আমার পেছনে চার বছরে ৭-৮ লাখ টাকা ভর্তুকি দিচ্ছে, আমি আমার দেশকে কি দিচ্ছি? আমি এ সিটটিতে ভর্তি হওয়ার কারনে আর একটা ছেলে বঞ্চিত হয়েছে। আবার মানচিত্রের গল্পে ফিরে আসি। আমি যদি আমার নৈতিক শিক্ষা বিশ্ববিদ্যালয় থেকে নিয়ে জেতে না পারি, তাহলে মানচিত্রের পেছনের মানুষটাকে আমি জোড়া দিতে পারব না। তার চোখদুটোকে আমি অন্ধ করে ফেললাম। সে তার সামনে ঘটে যাওয়া অন্যায়-অপরাধ কিছুই দেখতে পারবে না। এতে দেশের মানচিত্র ফুটো হয়ে যাবে। বাংলাদেশ তো আর এমনি এমনি দুর্নীতিতে চ্যাম্পিয়ন হয় নি। ভিসি স্যার প্রাইভেট বিশ্ববিদ্যালয়ে ক্লাস না করালে দেশের ক্ষতি হয়, আমি একটা ক্লাস না করলে দেশের ক্ষতি হয়, ফুড ডিপার্টমেন্টের ছেলেরা ১১ মাস ক্লাস না করলে দেশের ক্ষতি হয়, কিন্তু আমি যদি নৈতিকতা না শিখি তাহলে কি দেশের ক্ষতি হয় না? কোনটা বড়, ১ ঘণ্টার একটা ক্লাস না করা নাকি ২৫-৩০ বছরের কর্মজীবনে দুর্নীতি করে যাওয়া। দেশের বড় ক্ষতি কে করছে, আমি, যে একটা ক্লাস না করে অপরাধ করেছি নাকি, বিশ্ববিদ্যালয় প্রশাসন, যারা আমাকে নৈতিকতার শিক্ষা থেকে বঞ্ছিত করছে? দেশের এত বড় ক্ষতি করার পর তারা বিবেকের কাছে কি জবাব দেবে? নাকি বিবেক নামক বস্তুটার সাথে তাদের পরিচয় নেই? বিশ্ববিদ্যালয়ে কোন অনিয়ম দেখলে আমার খারাপ লাগে। প্রতিবাদ করতে ইচ্ছে করে। কিন্তু আমি কিছু বললেই ওই একই প্রশ্ন- > তোমার আইডি কত? মাওলানা ভাসানী বিজ্ঞান ও প্রযুক্তি বিশ্ববিদ্যালয়ের ১৭০০ ছাত্রের মধ্যে ১ বছরে ৫২ জনের বহিষ্কার। বাংলাদেশের আর কোন বিশ্ববিদ্যালয়ে এ রেকর্ড আছে কিনা আমার জানা নেই। প্রশাসন তার অযোগ্যতা ঢাকার জন্য বহিষ্কারাদেশ দিয়েই যাচ্ছে। এই নোটটার জন্য আমার উপর বহিষ্কারাদেশ চলে এসে কিনা তার নিশ্চয়তা নেই। তবুও বিড়ালের গলায় কাউকে না কাউকে ঘণ্টা বাঁধতেই হবে। যেখানে অন্যায়ের বিরুদ্ধে কিছু করার থাকে না সেখানে তাকে নাকি ঘৃণা করতে হয়। আমরা তাদের বিরুদ্ধে কিছু করতে না পারি, তাদেরকে অন্তত সমর্থন না দেই, ঘৃণা করতে শিখি। আমারতো মনে হয় বিশ্ববিদ্যালয় প্রশাসনের বিবেক না থাকলেও আমাদের আছে। আমরা বিবেকের এ দায় এড়াব কিভাবে? --- # আগন্তুকের ভুবনে স্বাগতম > Welcome to my blog. Published: 2010-12-09 URL: https://milon.im/post/aguntuk-er-vubone-swagotom.md আমার ব্লগটা শেষ পর্যন্ত চালুই করে দিলাম। আপনি আপনার মূল্যবান ব্যান্ডউইথ খরচ করে আমার ব্লগ দেখতে এসেছেন, আপনাকে ধন্যবাদ। এই ব্লগে আমি যা লিখব তা আমার একান্তই ব্যক্তিগত মতামত। কাউকে আঘাত করে কিছু বলা আমার উদ্দেশ্য নয়। তবুও কেউ যদি আমার লেখায় কষ্ট পেয়ে থাকেন, তার জন্য আগাম ক্ষমা চেয়ে নিচ্ছি। যারা কষ্ট করে মন্তব্য করবেন, তাদেরকে বলি, এটা একটা উস্মুক্ত ব্লগ। এমন কোন মন্তব্য করবেন না যা আমি প্রকাশ করতে পারব না। আপনার মন্তব্য প্রকাশ না করে Trash(আবর্জনার বাক্স) এ ফেলে রাখতে আমার খারাপই লাগবে। আবারো ধন্যবাদ, আপনাকে। --- # Why you should consider statically generated site for your next website? > I presented this on an audiance for an online PHP meetup in Berlin. Published: 2021-07-10 URL: https://milon.im/talk/why-you-should-consider-statically-generated-site-for-your-next-website.md Since the corona pandemic hits, there was hardly any in person meetup. A local PHP meetup group arranged an online meetup here in Berlin, Germany. I gave a small talk about statically generated sites, and why this might be the great choice for your next pet project. --- # Klassroom presents the Techtalk: Scaling API with Laravel > I was interviewed by Sumon Molla Selim on his web podcast about APIs and how to create them with Laravel. Published: 2020-05-09 URL: https://milon.im/talk/klassroom-presents-techtalk-scaling-api-with-laravel.md I was invited to talk about Laravel API development and scaling on Muhammad Sumon Molla Selim's weekly web podcast **Klassroom presents the Techtalk**. We talked about a bunch of different things about API development for about 2 hours. Here are the gist of my talk and various references on how to build and maintain a suntainable API in Laravel. #### STEP 1 - Just returning an array as response will make an API. Laravel's Response class implements Arrayable, Jsonable, ArrayObject and JsonSerializable interface. So, anything that implements these interface will return a json response. - Laravel Eloquent makes it even easier, just return any Model object or Collection, it will automatically cast it to json. Even it has built in feature to hide any specific column from the entity through `$hidden` attribute. It also protect us from mass assignment. - It has built in middlewares to take care of CORS, API throttling and other common issues. - Laravel has builtin auditing feature like `created_at`, `updated_at` timestamp, and it's very easy to add `created_by`, `updated_by` to your model. - Use proper HTTP response code and headers in your response. - Use proper HTTP verb and stick with one convention for for URL pattern. #### STEP 2 - You should never expose your database schema through API. You could use Laravel's API Resource to transform your Model response. For more control use something like [`league/fractal`](https://fractal.thephpleague.com/), or it's laravel bridge [`spatie/laravel-fractal`](https://github.com/spatie/laravel-fractal) for ease of use. - Don't expose your database IDs. Use generated complex id like `uuid`. You could use [`ramsey/uuid`](https://uuid.ramsey.dev/). - Do proper validation. Use laravel's validator, give proper validation error response. - Use Eloquent as long as it's serving your purpose, but don't hesitate to jump to SQL. - Consider your database a shared resource, even a single slow endpoint can make the whole API suite slower. - Use a profiler like [blackfire.io](https://blackfire.io/) or at least use [`barryvdh/laravel-debugbar`](https://github.com/barryvdh/laravel-debugbar). - Don't return the full model object where only a few column needed. Allow user to ask for the data they needed. You could use something like [`spatie/laravel-query-builder`](https://github.com/spatie/laravel-query-builder) for that. You could also enable sorting feature by using [`spatie/eloquent-sortable`](https://github.com/spatie/eloquent-sortable) package. - Always return paginated response while returning a Collection. If needed make an option to ask for the number of objects they needed. - Do not hard delete sensitive data, use soft delete instead. - Use a proper monitoring tool for your API like [newrelic](https://newrelic.com/). #### STEP 3 - For API authentication you could use simple [token based authentication](https://laravel.com/docs/6.x/api-authentication), [JWT](https://jwt-auth.readthedocs.io/en/develop/), [Sanctum](https://laravel.com/docs/7.x/sanctum#introduction) or [Passport](https://laravel.com/docs/7.x/passport) based on your need. - For advanced searching use something like [Laravel Scout](https://laravel.com/docs/7.x/scout). - Use caching where ever possible, use proper [`ETag`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) header, and handle [`If-None-Match`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) header in the request. Laravel also provide a [`cache.headers`](https://laravel.com/docs/7.x/responses#attaching-headers-to-responses) middleware out of the box, you can use that to handle api caching too. - Do not load unused classes, disable them from `config/app.php` file. - For localization, you can use [`spatie/laravel-translatable`](https://github.com/spatie/laravel-translatable) package. #### STEP 4 - Use [`HATEOAS`](https://en.wikipedia.org/wiki/HATEOAS) (Hypermedia as the Engine of Application State). - Use an API standard like [`json:api`](https://jsonapi.org/), you could use [`cloudcreativity/laravel-json-api`](https://laravel-json-api.readthedocs.io/en/latest/), [`cloudcreativity/json-api-testing`](https://laravel-json-api.readthedocs.io/en/latest/) and [`spatie/laravel-json-api-paginate`](https://github.com/spatie/laravel-json-api-paginate) to easily achieve that. Column filter and compound documents implies almost the same features as GraphQL. - Use proper API versioning, maintain backward compatibility. - Write test, test, test! - Use custom response code for explaining different situation if your API suite id fairly big like Braintree does for their APIs. Enjoy!! --- # Telenor Health - Tonic Application Architecture > I presented this on an internal session to all the team members of Telenor Health including developers, dev ops, QA and all. Published: 2018-03-29 URL: https://milon.im/talk/th-tonic-application-architecture.md We arranged a tech talk session on every Thursday on Telenor Health. This was the very first session of that. I talked about the all the stream, which I am taking care of. Though I have worked on every single project of Telenor Health, these are the projects only I built and maintained. --- # Laravel Bangladesh Meetup 1.0 Presentation > My presentation slides on 1st ever Laravel meetup of Bangladesh. Published: 2017-11-20 URL: https://milon.im/talk/laravel-bangladesh-meetup-presentation.md Recently(18th November, 2017) I have attended the first ever Laravel meetup of Bangladesh. It was held at World University of Bangladesh(WUB) Panthapath Campus. Around 330 people attended the meetup. 4 speaker presented their talk at the meetup. Our venue partner was WUB and sponsor was Techmasters.
The title of my speech was High Performance Laravel, was basically about how you can optimize Laravel for handle high traffic website and APIs. Here is the slides of that speech. Enjoy.
--- # Talk.js meet up presentation > My presentation slides of Talk.js meetup. Published: 2016-04-17 URL: https://milon.im/talk/talk-js-meet-up-presentation.md Yesterday I gave a speech on [talk.js](https://www.facebook.com/groups/talkjs.net) meet up. My presentation's title was JavaScript for the rest of us. It was on [vue.js](http://vuejs.org) actually. The title is little weird as the context is different. My motivation was, I am going to introduce vue.js to those group, whose are actually backend developers, write mostly server rendered application, use a very least amount of javascript for improving user interaction. This group mostly used jQuery for their JS need. My goal is to introduce themselves with a wonderful framework, which has a very little footprint and a very elegant syntax to improve their js code. As my talks' title was little weird, [Mafinar Bhai](https://www.facebook.com/mafinar) trolled me a lot, and he promised he will continue this for the next three or four months. I will try to enjoy those. 🙂 --- # phpXperts Meetup-01 Presentation > My presentation slides of phpXperts meetup held at HubDhaka. Published: 2015-06-01 URL: https://milon.im/talk/phpxperts-meetup-01-presentation.md I give a speech on first [phpXperts](https://www.facebook.com/groups/pxperts) meetup on 30th May, 2015 at [Hubdhaka](http://www.hubdhaka.com). Here is the presentation of that slide. The main focus of my talk was the new features that are coming with Laravel PHP Framework 5.1. Thanks...