<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Vibe-Coding on miti99</title><link>https://miti99.com/tags/vibe-coding/</link><description>Recent content in Vibe-Coding on miti99</description><generator>Hugo -- gohugo.io</generator><language>vi</language><lastBuildDate>Mon, 28 Sep 2026 09:33:15 +0700</lastBuildDate><atom:link href="https://miti99.com/tags/vibe-coding/index.xml" rel="self" type="application/rss+xml"/><item><title>Newsletter #53</title><link>https://miti99.com/post/2025/09/09/</link><pubDate>Tue, 09 Sep 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/09/09/</guid><description>&lt;p&gt;&lt;em&gt;&lt;del&gt;Bài này mình thử nghiệm tổng hợp tất cả code agent rules trước đây về thành 1 file AGENTS.md duy nhất, sau đó trỏ CLAUDE.md đọc file này.&lt;/del&gt; Mời bạn thưởng thức Newsletter #53.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="anti-cheat-secure-boot--tpm"&gt;&lt;a class="link" href="https://andrewmoore.ca/blog/post/anticheat-secure-boot-tpm/" target="_blank" rel="noopener"
&gt;Anti-cheat, Secure Boot &amp;amp; TPM&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Andrew Moore giải thích vì sao các hệ thống chống gian lận (anti-cheat) như của Battlefield 6 hay Vanguard của Riot bắt đầu yêu cầu người chơi bật Secure Boot và TPM 2.0, đồng thời phản bác ý kiến cho rằng đây là cái cớ để thu thập dữ liệu người chơi. Secure Boot dựa trên một hệ thống phân cấp khóa (Platform Key, Key Exchange Key, cơ sở dữ liệu chữ ký được phép DB và bị cấm DBX) để đảm bảo firmware chỉ chạy những ảnh khởi động đã được ký hợp lệ. Kết hợp với việc Windows chỉ nạp driver nhân (kernel) có chữ ký của Microsoft, kẻ viết phần mềm gian lận khó đưa mã vào kernel nếu không có lỗ hổng chưa được vá.&lt;/p&gt;
&lt;p&gt;Tuy nhiên, anti-cheat không thể tin hệ điều hành khi nó báo Secure Boot đang bật, nên TPM mới là mắt xích then chốt. fTPM tích hợp sẵn trong CPU của AMD và Intel có một Endorsement Key duy nhất, được chứng thực bằng chứng chỉ của nhà sản xuất, giúp nhận diện phần cứng mà không thể giả mạo; nhờ đó lệnh cấm theo phần cứng buộc người gian lận phải mua CPU mới. Bên cạnh đó, các thanh ghi PCR lưu chuỗi băm của mọi sự kiện trong quá trình khởi động, và qua cơ chế chứng thực từ xa bằng lệnh &lt;code&gt;TPM2_Quote&lt;/code&gt;, nhà cung cấp anti-cheat có thể xác minh môi trường khởi động chưa bị can thiệp. Kết luận: giải pháp này không xóa bỏ hoàn toàn gian lận, nhất là gian lận dựa trên phần cứng, nhưng khiến việc né lệnh cấm tốn kém hơn nhiều, không ảnh hưởng đến quyền riêng tư, và là một lớp quan trọng trong chiến lược phòng thủ nhiều tầng.&lt;/p&gt;
&lt;h2 id="left-to-right-programming"&gt;&lt;a class="link" href="https://graic.net/p/left-to-right-programming" target="_blank" rel="noopener"
&gt;Left to Right Programming&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Tác giả lập luận rằng chương trình nên luôn hợp lệ ngay trong lúc đang gõ, để trình soạn thảo có thể gợi ý và kiểm tra lỗi ở từng bước. Ví dụ điển hình là list comprehension của Python: khi viết &lt;code&gt;words_on_lines = [line.split() for line in text.splitlines()]&lt;/code&gt;, biến &lt;code&gt;line&lt;/code&gt; được dùng trước khi được khai báo, nên trình soạn thảo không biết kiểu dữ liệu để gợi ý phương thức. Ngược lại, với Rust (&lt;code&gt;let words_on_lines = text.lines().map(|line| line.split_whitespace());&lt;/code&gt;) hay JavaScript, chương trình được xây dựng từ trái sang phải: biến được khai báo trước, và ngay khi gõ dấu chấm, trình soạn thảo đã có thể đề xuất các phương thức phù hợp.&lt;/p&gt;
&lt;p&gt;Bài viết liên hệ với nguyên tắc thiết kế &amp;ldquo;progressive disclosure&amp;rdquo;: độ phức tạp chỉ nên xuất hiện khi người dùng thực sự cần đến nó. Trong C, vì không thể gắn phương thức vào struct, bạn phải biết trước tên các hàm như &lt;code&gt;fread&lt;/code&gt; hay &lt;code&gt;fclose&lt;/code&gt; thay vì tình cờ khám phá chúng qua gợi ý khi gõ &lt;code&gt;file.&lt;/code&gt;. Python cũng gặp vấn đề tương tự với các hàm toàn cục như &lt;code&gt;len&lt;/code&gt; hay &lt;code&gt;map&lt;/code&gt;; khi logic phức tạp hơn, một dòng Python lồng nhiều &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;lambda&lt;/code&gt; và comprehension trở nên khó đọc hơn hẳn so với chuỗi phương thức trong JavaScript vốn đọc tuần tự từ trái sang phải. Thông điệp cuối cùng dành cho người thiết kế ngôn ngữ và thư viện rất ngắn gọn: hãy tạo ra những API dễ khám phá.&lt;/p&gt;
&lt;h2 id="big-o-notation"&gt;&lt;a class="link" href="https://samwho.dev/big-o/" target="_blank" rel="noopener"
&gt;Big O Notation&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết trên samwho.dev giới thiệu Big O notation một cách trực quan với nhiều ví dụ tương tác ngay trong trình duyệt. Thay vì đo thời gian chạy thực tế (wall-clock time), Big O mô tả thời gian thực thi tăng lên như thế nào khi kích thước đầu vào tăng. Tác giả trình bày bốn nhóm độ phức tạp phổ biến: hàm tính tổng từ 1 đến n bằng vòng lặp là O(n) (tuyến tính), còn dùng công thức &lt;code&gt;(n*(n+1))/2&lt;/code&gt; thì đạt O(1) (hằng số), dù O(1) không có nghĩa là &amp;ldquo;tức thì&amp;rdquo; mà chỉ là thời gian không phụ thuộc vào đầu vào. Bubble sort là ví dụ cho O(n²) (bậc hai), còn trò chơi đoán số từ 1 đến 100 bằng tìm kiếm nhị phân, loại bỏ một nửa khả năng sau mỗi lần đoán, minh họa O(log n) (logarit). Bài cũng nhấn mạnh rằng Big O chỉ giữ lại số hạng gọn nhất (không có O(2n)) và mặc định mô tả trường hợp xấu nhất.&lt;/p&gt;
&lt;p&gt;Phần cuối đưa ra các mẹo cải thiện hiệu năng thực tế: dùng &lt;code&gt;Set&lt;/code&gt; để tra cứu với độ phức tạp O(1) thay vì duyệt mảng (dù việc tạo &lt;code&gt;Set&lt;/code&gt; tốn O(n)), tránh gọi &lt;code&gt;.indexOf&lt;/code&gt; bên trong vòng lặp vì sẽ biến cả hàm thành O(n²), và lưu đệm kết quả trung gian như trong hàm tính giai thừa để tránh tính lại, đổi lại tốn thêm bộ nhớ. Lời khuyên quan trọng nhất: luôn đo hiệu năng trước và sau khi thay đổi mã nguồn, đừng mặc định tin vào những gì đọc được trên mạng.&lt;/p&gt;
&lt;h2 id="personal-ai-evaluations-august-2025"&gt;&lt;a class="link" href="https://darkcoding.net/software/personal-ai-evals-aug-2025/" target="_blank" rel="noopener"
&gt;Personal AI Evaluations August 2025&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Graham King tự đánh giá các mô hình ngôn ngữ lớn (LLM) theo nhu cầu cá nhân thay vì dựa vào bảng xếp hạng: anh chọn các câu hỏi thật từ 130 prompt trong lịch sử bash, chia thành bốn nhóm (lập trình, quản trị hệ thống, giải thích kỹ thuật, kiến thức chung và sáng tạo), rồi chạy trên 11 mô hình qua OpenRouter như Claude Sonnet 4, DeepSeek, Gemini 2.5 Flash và Pro, Kimi K2, GPT-OSS-120B, Qwen3 và GLM 4.5. Anh tự viết công cụ bằng Rust để ẩn danh câu trả lời khi chấm điểm, đồng thời ghi lại chi phí, độ trễ và thông lượng của từng mô hình.&lt;/p&gt;
&lt;p&gt;Kết luận chính là hầu hết mô hình đều trả lời tốt, nên chi phí và độ trễ mới là yếu tố quyết định. Các mô hình đóng như Gemini 2.5 Pro và Claude Sonnet không hề vượt trội, thậm chí thường kém hơn mô hình mở mà lại đắt hơn rất nhiều. Gemini 2.5 Flash nhanh nhất; Kimi K2, Qwen3 và DeepSeek thuộc nhóm rẻ nhất; còn hai mô hình DeepSeek và hai mô hình Qwen3 có độ chính xác trung bình tốt nhất. Chế độ suy luận (reasoning) hiếm khi giúp ích, ngoại trừ bài làm thơ, và cả quá trình chỉ ghi nhận một lần &amp;ldquo;ảo giác&amp;rdquo; khi GPT-OSS-120B bịa ra một bộ phim không tồn tại. Từ đó, tác giả chọn cách hỏi nhiều mô hình cùng lúc bằng tmux: DeepSeek cho câu hỏi hằng ngày, thêm Gemini Flash và Qwen3 khi cần ý kiến thứ hai, và nhóm mô hình suy luận cho những câu hỏi khó.&lt;/p&gt;
&lt;h2 id="how-to-keep-services-running-during-failures"&gt;&lt;a class="link" href="https://newsletter.scalablethread.com/p/how-to-keep-services-running-during" target="_blank" rel="noopener"
&gt;How to Keep Services Running During Failures&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết từ The Scalable Thread giới thiệu graceful degradation, nguyên tắc thiết kế giúp hệ thống vẫn giữ được chức năng cốt lõi khi một phần gặp sự cố thay vì sập hoàn toàn. Chẳng hạn, nếu dịch vụ gợi ý của một nền tảng video bị lỗi, trang vẫn có thể hiển thị danh sách video phổ biến trong khi chức năng phát video hoạt động bình thường. Nhóm chiến lược đầu tiên tập trung kiểm soát lưu lượng: rate limiting giới hạn số yêu cầu trong các đợt khuyến mãi lớn hay tấn công từ chối dịch vụ; request coalescing gộp hàng nghìn truy vấn giống nhau thành một để giảm tải cho cơ sở dữ liệu; load shedding chủ động bỏ các yêu cầu không quan trọng (như ghi nhận lượt nhấp) để ưu tiên giao dịch mua hàng; và thử lại kèm jitter, tức thêm độ trễ ngẫu nhiên, giúp tránh &amp;ldquo;thundering herd problem&amp;rdquo; khi dịch vụ vừa phục hồi.&lt;/p&gt;
&lt;p&gt;Nhóm chiến lược thứ hai xử lý lỗi và tăng khả năng quan sát hệ thống. Circuit breaker hoạt động như cầu dao điện: khi dịch vụ thanh toán liên tục lỗi, dịch vụ đặt hàng sẽ ngắt mạch và trả lỗi ngay lập tức trong một khoảng thời gian (ví dụ 60 giây), sau đó mới cho vài yêu cầu đi qua để kiểm tra dịch vụ đã hồi phục chưa. Request timeout ngăn dịch vụ phía trên cạn kiệt luồng xử lý hay kết nối vì phải chờ một dịch vụ chậm. Cuối cùng, giám sát và cảnh báo dựa trên các chỉ số như tỷ lệ lỗi, độ trễ hay độ dài hàng đợi của message broker giúp kỹ sư phát hiện và xử lý sự cố trước khi nó lan rộng.&lt;/p&gt;
&lt;h2 id="why-was-apache-kafka-created"&gt;&lt;a class="link" href="https://bigdata.2minutestreaming.com/p/why-was-apache-kafka-created" target="_blank" rel="noopener"
&gt;Why Was Apache Kafka Created?&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết từ 2 Minute Streaming giải thích vì sao Kafka ra đời. Khoảng năm 2012, LinkedIn dùng dữ liệu hoạt động của người dùng cho nhiều tính năng cốt lõi, nhưng lại vận hành hai đường ống dữ liệu riêng biệt: một hệ thống xử lý theo lô hằng giờ, gửi thông điệp XML qua máy chủ HTTP để nạp vào kho dữ liệu Oracle và Hadoop, và một hệ thống gần thời gian thực cho số liệu giám sát chạy trên Zenoss. Cả hai đều tốn công vận hành thủ công, tồn đọng lớn, và chỉ là đường ống điểm-tới-điểm không tích hợp được với nhau. Những vấn đề cụ thể gồm phải phân tích hàng trăm schema XML, khó thay đổi schema mà không làm hỏng hệ thống phía sau, độ trễ tính bằng giờ, và dữ liệu sạch chỉ nằm trong kho dữ liệu.&lt;/p&gt;
&lt;p&gt;Kafka giải quyết các vấn đề đó nhờ kiến trúc phân tán có nhân bản, mở rộng theo chiều ngang bằng partition, cấu trúc log cho phép nhiều bên đọc cùng lúc, và lưu dữ liệu xuống đĩa để tách bên ghi khỏi bên đọc. LinkedIn còn chuyển từ XML sang Avro (nhỏ hơn khoảng 7 lần), xây dựng dịch vụ quản lý phiên bản schema, tiền thân của Schema Registry, kèm cơ chế kiểm tra tương thích ngược, áp dụng mô hình &amp;ldquo;schema on write&amp;rdquo; để làm sạch dữ liệu ngay khi vào Kafka, và chuyển trách nhiệm định nghĩa schema về cho đội tạo ra dữ liệu cùng quy trình duyệt bắt buộc. Điều khiến tác giả bất ngờ là tài liệu gốc đã đề cao schema từ hơn 13 năm trước, trong khi ông coi việc thiếu hỗ trợ schema bẩm sinh là sai lầm lớn nhất của Kafka.&lt;/p&gt;
&lt;h2 id="how-we-vibe-code-at-a-faang"&gt;&lt;a class="link" href="https://www.reddit.com/r/vibecoding/comments/1myakhd/how_we_vibe_code_at_a_faang/" target="_blank" rel="noopener"
&gt;How We Vibe Code at a FAANG&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Một kỹ sư AI với hơn mười năm kinh nghiệm, một nửa trong số đó làm tại FAANG, chia sẻ trên Reddit cách nhóm của anh đưa AI vào quy trình phát triển phần mềm cho môi trường vận hành thật, nhằm phản bác ý kiến rằng lập trình có AI hỗ trợ không thể dùng cho sản phẩm thực tế. Quy trình vẫn bắt đầu từ tài liệu thiết kế kỹ thuật: bản đề xuất cần được các bên liên quan đồng thuận, sau đó là thiết kế hệ thống đầy đủ về kiến trúc và tích hợp với các đội khác, rồi đến buổi đánh giá thiết kế nơi các kỹ sư cấp cao &amp;ldquo;mổ xẻ&amp;rdquo; kỹ lưỡng, điều tác giả gọi là dồn cái khó lên phía trước. Tiếp theo là tài liệu hóa từng hệ thống con, lập danh sách công việc và lên kế hoạch sprint cùng PM và TPM.&lt;/p&gt;
&lt;p&gt;Chỉ đến giai đoạn viết mã, AI mới trở thành &amp;ldquo;cấp số nhân&amp;rdquo; cho năng suất: nhóm áp dụng Test Driven Development, để AI agent viết kiểm thử trước rồi mới xây dựng tính năng. Mã nguồn cần hai lập trình viên phê duyệt trước khi được hợp nhất (AI cũng bắt đầu hỗ trợ khâu duyệt mã), rồi được kiểm thử trên môi trường staging trước khi triển khai chính thức. Kết quả là thời gian từ lúc đề xuất tính năng đến khi đưa lên môi trường thật nhanh hơn khoảng 30%. Nhiều bình luận cho rằng đây thực chất không phải &amp;ldquo;vibe coding&amp;rdquo; mà là lập trình có AI hỗ trợ trong một quy trình doanh nghiệp bài bản, và chính tác giả cũng đồng ý với cách gọi đó.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Đánh giá hiệu quả của AGENTS.md: Chưa được tốt lắm, còn chứa tiếng Anh nhiều. Mình sẽ cố gắng cải thiện thêm trong các bài viết tới. Hẹn gặp lại&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #41</title><link>https://miti99.com/post/2025/07/31/</link><pubDate>Thu, 31 Jul 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/07/31/</guid><description>&lt;p&gt;&lt;em&gt;Mời bạn thưởng thức Newsletter #41.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="the-fastest-way-to-detect-a-vowel-in-a-string"&gt;&lt;a class="link" href="https://austinhenley.com/blog/vowels.html" target="_blank" rel="noopener"
&gt;The Fastest Way to Detect a Vowel in a String&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Austin Henley thử so sánh 11 cách kiểm tra một chuỗi có chứa nguyên âm hay không trong Python, từ vòng lặp &lt;code&gt;for&lt;/code&gt; đơn giản, vòng lặp kiểu C với chuỗi điều kiện &lt;code&gt;or&lt;/code&gt;, vòng lặp lồng nhau, phép giao tập hợp, biểu thức generator với &lt;code&gt;any()&lt;/code&gt;, đệ quy, &lt;code&gt;filter&lt;/code&gt;/&lt;code&gt;map&lt;/code&gt; với lambda, cho đến regex và cả một cách &amp;ldquo;cho vui&amp;rdquo; là mã hóa ký tự bằng số nguyên tố. Kết quả đo đạc khá bất ngờ: với chuỗi ngắn (độ dài 10), vòng lặp đơn giản nhanh nhất, nhưng từ độ dài 100 trở lên thì regex vượt lên dẫn đầu, còn vòng lặp kiểu C chậm hẳn đi. Lý do là bộ máy regex được viết bằng C và dùng bảng tra bitmap để khớp ký tự, thay vì phải thông dịch từng lệnh bytecode của Python.&lt;/p&gt;
&lt;p&gt;Phần cập nhật sau bài viết còn thú vị hơn: độc giả chỉ ra rằng phương thức &lt;code&gt;find()&lt;/code&gt; có sẵn của chuỗi nhanh hơn regex nhờ thuật toán tìm kiếm được tối ưu trong CPython, và chỉ cần đảo thứ tự vòng lặp (duyệt qua từng nguyên âm rồi kiểm tra nó có nằm trong chuỗi đầu vào không) là đã nhanh hơn cả regex lẫn &lt;code&gt;find()&lt;/code&gt;, gấp khoảng 16 lần regex với chuỗi dài. Bài học rút ra là chênh lệch hiệu năng ở đây chủ yếu đến từ trình thông dịch CPython: đoạn mã nào đẩy được nhiều việc xuống tầng C thì thắng. Trong thực tế, bạn nên ưu tiên cách viết dễ đọc, trừ khi phải xử lý hàng triệu chuỗi.&lt;/p&gt;
&lt;h2 id="writing-toy-software-is-a-joy"&gt;&lt;a class="link" href="https://blog.jsbarretto.com/post/software-is-joy" target="_blank" rel="noopener"
&gt;Writing Toy Software Is A Joy&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Joshua Barretto khuyến khích lập trình viên viết &amp;ldquo;phần mềm đồ chơi&amp;rdquo; — những dự án nhỏ, tự làm từ đầu — để hiểu sâu cách mọi thứ vận hành và tìm lại niềm vui lập trình. Xuất phát từ câu nói của Richard Feynman &amp;ldquo;Những gì tôi không thể tạo ra, tôi không hiểu được&amp;rdquo;, tác giả cho rằng tự tay xây dựng một phiên bản đơn giản của công cụ quen thuộc giúp bạn nắm được những ràng buộc cốt lõi của nó tốt hơn nhiều so với chỉ đọc lý thuyết. Nguyên tắc chủ đạo là quy tắc 80:20: bỏ ra 20% công sức để có 80% chức năng, chỉ cài đặt những gì thật sự cần và cứ để chương trình lỗi cho đến khi buộc phải xử lý trường hợp biên. Cách làm này giúp những phần mềm tưởng chừng phức tạp trở nên vừa sức.&lt;/p&gt;
&lt;p&gt;Bài viết đưa ra 23 ý tưởng kèm mức độ khó (từ 3 đến 8 trên thang 10), thời gian ước tính và tài liệu tham khảo: dễ thì có bộ máy regex, trình giả lập CHIP-8, bảng băm, trình thông dịch; trung bình có physics engine, trình soạn thảo văn bản, voxel engine, mô phỏng quỹ đạo; khó nhất là nhân hệ điều hành x86 và trình biên dịch cho ngôn ngữ giống C. Tác giả đặc biệt khuyên không dùng các mô hình ngôn ngữ lớn (LLM) cho những dự án này, vì kiến thức không nên được &amp;ldquo;dọn sẵn lên đĩa&amp;rdquo;: chính quá trình tự mày mò và vật lộn với vấn đề mới tạo ra giá trị học tập, trong bối cảnh phát triển phần mềm ngày càng bị hàng hóa hóa và phụ thuộc vào AI.&lt;/p&gt;
&lt;h2 id="field-notes-from-shipping-real-code-with-claude"&gt;&lt;a class="link" href="https://diwank.space/field-notes-from-shipping-real-code-with-claude" target="_blank" rel="noopener"
&gt;Field Notes From Shipping Real Code With Claude&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Diwank chia sẻ kinh nghiệm dùng Claude để viết mã nguồn chạy thật trong môi trường sản phẩm. Tác giả chia cách làm việc với AI thành ba chế độ: chế độ &amp;ldquo;sân chơi&amp;rdquo; cho dự án cuối tuần hay bản thử nghiệm, nơi Claude viết 80–90% mã nguồn với rất ít rào chắn; chế độ lập trình cặp cho dự án dưới khoảng 5.000 dòng; và quy mô sản phẩm/monorepo với người dùng thật, nơi mọi thứ phải được điều phối cẩn thận. Nền tảng của cả quy trình là file &lt;code&gt;CLAUDE.md&lt;/code&gt;, đóng vai trò như &amp;ldquo;hiến pháp&amp;rdquo; của codebase: ghi lý do các quyết định kiến trúc, quy tắc viết mã, cách chạy kiểm thử, quy ước repo và những điều bị cấm. Bên cạnh đó là các &amp;ldquo;anchor comment&amp;rdquo; như &lt;code&gt;AIDEV-NOTE:&lt;/code&gt; — ngắn gọn, dễ grep, vừa dẫn đường cho AI vừa làm tài liệu cho con người.&lt;/p&gt;
&lt;p&gt;Quy tắc bất di bất dịch là con người viết kiểm thử, vì kiểm thử mã hóa yêu cầu nghiệp vụ và các trường hợp biên mà AI không nắm được; tác giả minh họa bằng một bộ kiểm thử do AI sinh ra vẫn chạy qua nhưng bỏ sót lỗi rò rỉ bộ nhớ. AI tuyệt đối không được sửa file kiểm thử, thay đổi hợp đồng API, đụng vào migration cơ sở dữ liệu, commit secrets hay tự suy đoán logic nghiệp vụ. Tác giả còn gợi ý dùng git worktree cho các thử nghiệm với AI, gắn nhãn &lt;code&gt;[AI]&lt;/code&gt; cho commit có AI hỗ trợ, và ở cấp độ đội nhóm thì công khai minh bạch việc dùng AI, thống nhất quy tắc từ đầu, vì thực hành phát triển tốt chính là ranh giới giữa AI khuếch đại năng lực và AI gây hỗn loạn.&lt;/p&gt;
&lt;h2 id="why-generative-ai-coding-tools-and-agents-do-not-work-for-me"&gt;&lt;a class="link" href="https://blog.miguelgrinberg.com/post/why-generative-ai-coding-tools-and-agents-do-not-work-for-me" target="_blank" rel="noopener"
&gt;Why Generative AI Coding Tools and Agents Do Not Work For Me&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Miguel Grinberg, tác giả Flask-SocketIO và nhiều thư viện Python quen thuộc, giải thích vì sao các công cụ và agent AI sinh mã nguồn không phù hợp với ông. Lập luận chính là chúng không giúp ông làm nhanh hơn: vì luôn là người chịu trách nhiệm cho mã nguồn mình đưa lên môi trường sản phẩm, dù có AI hay không, ông phải đọc và hiểu kỹ từng dòng trước khi commit. Việc review mã nguồn do AI viết mất ngang bằng, thậm chí lâu hơn tự viết, nên phần thời gian &amp;ldquo;tiết kiệm&amp;rdquo; được bị triệt tiêu ngay ở khâu kiểm tra bắt buộc này.&lt;/p&gt;
&lt;p&gt;Grinberg cũng phản bác phép so sánh AI với thực tập sinh: thực tập sinh học hỏi và dần tự chủ theo thời gian, còn công cụ AI không có trí nhớ giữa các phiên, mỗi tác vụ mới lại quay về vạch xuất phát như một thực tập sinh mắc chứng mất trí nhớ. Ông coi việc tự học ngôn ngữ và framework mới là niềm vui và là khoản đầu tư cho nghề, không phải trở ngại cần giao cho AI. Với các đóng góp từ cộng đồng mã nguồn mở, dù cũng phải review kỹ, ông nhận lại được thứ AI không mang lại: tương tác thật giữa con người, phản hồi và những ý tưởng mới giúp dự án tốt hơn.&lt;/p&gt;
&lt;h2 id="ai-coding-assistants-aren"&gt;&lt;a class="link" href="https://leaddev.com/velocity/ai-coding-assistants-arent-really-making-devs-feel-more-productive" target="_blank" rel="noopener"
&gt;AI coding assistants aren&amp;rsquo;t really making devs feel more productive&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Chantal Kapani, phóng viên của LeadDev, phân tích số liệu từ báo cáo Engineering Leadership Report 2025 (khảo sát 617 lãnh đạo kỹ thuật vào tháng 3) và cho thấy trợ lý lập trình AI chưa thực sự giúp lập trình viên cảm thấy năng suất hơn. Chỉ 6% người được hỏi ghi nhận năng suất tăng đáng kể, 39% thấy cải thiện nhỏ trong khoảng 1–10%. AI chủ yếu được dùng để sinh mã nguồn (47%), tái cấu trúc mã (45%), viết tài liệu (44%), giao tiếp nội bộ (28%) và sửa lỗi (22%). Con số này trái ngược hẳn với những tuyên bố lạc quan như số liệu 88% người dùng thấy năng suất hơn của GitHub hay JPMorgan Chase báo hiệu suất tăng 10–20%.&lt;/p&gt;
&lt;p&gt;Các chuyên gia được trích dẫn đưa ra một số lý do cho khoảng cách này: công cụ AI tập trung hẹp vào việc sinh mã nguồn mà bỏ qua những điểm nghẽn sâu hơn trong quy trình; nhiều công cụ được áp dụng theo sự hào hứng từ cấp trên thay vì được kiểm chứng từ dưới lên; độ trễ thật sự nằm ở thời gian chạy kiểm thử và chu kỳ triển khai chứ không phải thời gian gõ phím; và lập trình viên thường không được hỏi ý kiến khi triển khai. Kết luận chung là cần xác định đúng vấn đề thực tế của đội trước khi đưa AI vào giải quyết.&lt;/p&gt;
&lt;h2 id="how-to-vibe-code-as-a-senior-engineer"&gt;&lt;a class="link" href="https://blog.alexmaccaw.com/how-to-vibe-code-as-a-senior-engineer" target="_blank" rel="noopener"
&gt;How to Vibe Code as a Senior Engineer&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Alex MacCaw chia sẻ cách &amp;ldquo;vibe coding&amp;rdquo; hiệu quả dưới góc nhìn kỹ sư senior: để các mô hình AI đảm nhận phần lớn việc viết mã nguồn, còn kỹ sư định hướng bằng prompt rõ ràng và giám sát kiến trúc. Theo tác giả, điều kiện tiên quyết là một bộ khung dự án (scaffold) vững chắc như ai-monorepo-scaffold với sẵn ví dụ về migration, route, schema để AI học theo; các quy tắc trong &lt;code&gt;.cursor/rules&lt;/code&gt; buộc AI lập kế hoạch, giữ an toàn kiểu dữ liệu và kiểm thử, để nó cư xử như &amp;ldquo;một kỹ sư junior sạch sẽ, có trách nhiệm&amp;rdquo;; thêm mọi file liên quan (kể cả định nghĩa kiểu) vào ngữ cảnh; dùng Cursor vì phản hồi lint và kiểm tra kiểu gần như tức thì; và chọn mô hình hàng đầu như Claude Opus 4 hay Gemini 2.5 Pro ở chế độ &amp;ldquo;thinking&amp;rdquo;, ưu tiên chất lượng hơn chi phí token.&lt;/p&gt;
&lt;p&gt;Về cách viết prompt, MacCaw khuyên luôn yêu cầu AI đưa kế hoạch để duyệt trước khi viết mã, nói thật cụ thể về kết quả và vị trí file mong muốn, đưa ví dụ mẫu, đặt ràng buộc rõ ràng (chẳng hạn &amp;ldquo;tránh dùng &lt;code&gt;any&lt;/code&gt;&amp;rdquo;), giữ phạm vi hẹp và chuyển sang prompt dài, mang tính trò chuyện khi bị kẹt. Tác giả cũng chỉ ra các điểm yếu của AI: không tự biết cần ngữ cảnh gì, hay dùng &lt;code&gt;any&lt;/code&gt; thay cho kiểu TypeScript đúng, lao vào viết mã mà không xác nhận hướng đi, và thiếu con mắt thiết kế kiến trúc theo phong cách riêng của dự án. MacCaw gọi đây có thể là &amp;ldquo;hồi kết cuối cùng của lập trình do con người dẫn dắt&amp;rdquo; trước khi AI lấp nốt những khoảng trống còn lại.&lt;/p&gt;
&lt;h2 id="sql-noir---interactive-sql-game"&gt;&lt;a class="link" href="https://www.sqlnoir.com/blog/games-to-learn-sql" target="_blank" rel="noopener"
&gt;SQL Noir - Interactive SQL Game&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Hristo Bogoev, người tạo ra SQL Noir, tổng hợp năm trò chơi giúp học SQL thông qua trải nghiệm tương tác thay vì giáo trình khô khan. Đứng đầu là chính SQL Noir, trò chơi thám tử nơi bạn phá án bằng các truy vấn SQL, gồm sáu vụ án khó dần, lược đồ cơ sở dữ liệu thực tế, phản hồi ngay lập tức, có phần miễn phí và gói trả phí. Tiếp theo là SQL Island, trò chơi sinh tồn trên hoang đảo phù hợp cho người mới bắt đầu dù giao diện hơi cũ; SQL Murder Mystery của Đại học Northwestern, một vụ án duy nhất nhưng rất tốt để luyện phép JOIN; SQL Police Department (SQLPD), nền tảng trả phí với nhiều vụ án, gợi ý có hướng dẫn và cốt truyện chất lượng.&lt;/p&gt;
&lt;p&gt;Cuối cùng là SQLZoo, bộ bài tập tương tác đã hơn 20 năm tuổi, miễn phí và đi theo hệ thống từ cơ bản đến nâng cao như window function, dù không có yếu tố cốt truyện. Bài viết là một danh sách tham khảo hữu ích cho lập trình viên junior muốn luyện SQL theo cách thú vị: người mới có thể bắt đầu với SQL Island hoặc SQL Noir, rồi củng cố kiến thức nền với SQLZoo.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #32</title><link>https://miti99.com/post/2025/07/21/</link><pubDate>Mon, 21 Jul 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/07/21/</guid><description>&lt;p&gt;&lt;em&gt;Đã lâu rồi mình không viết bài. Và thú thật thì những newsletter dạo trước hơi kiểu &amp;ldquo;chạy KPI&amp;rdquo;, &lt;del&gt;mình cứ cố cho rất nhiều link vào và để AI Agent làm nốt phần còn lại&lt;/del&gt;. Lần này mình sẽ chọn lọc bài kĩ hơn, &lt;del&gt;còn viết thì vẫn để AI thôi, vì mình lười hehe =)))&lt;/del&gt;. Mong các bạn sẽ thích. Chào mừng bạn đến với Newsletter #31.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="claude-code-best-practices-for-agentic-coding"&gt;&lt;a class="link" href="https://code.claude.com/docs/en/best-practices" target="_blank" rel="noopener"
&gt;Claude Code: Best Practices for Agentic Coding&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Đây là tài liệu hướng dẫn chính thức của Anthropic, tổng hợp những cách làm việc hiệu quả với Claude Code - môi trường lập trình dạng agent có thể tự đọc tệp, chạy lệnh, sửa mã nguồn và xử lý vấn đề trong khi bạn quan sát hoặc điều hướng. Hầu hết lời khuyên đều xuất phát từ một giới hạn: cửa sổ ngữ cảnh (context window) đầy lên rất nhanh và chất lượng câu trả lời giảm dần khi nó đầy. Vì vậy, việc quan trọng nhất là cho Claude một cách tự kiểm chứng kết quả, chẳng hạn bộ kiểm thử, lệnh build hay ảnh chụp màn hình để so sánh, để nó tự lặp lại cho tới khi đạt thay vì bạn phải soát từng lỗi. Với tác vụ phức tạp, nên tách thành bốn bước: khám phá, lập kế hoạch (dùng plan mode), triển khai rồi commit; còn việc nhỏ như sửa lỗi chính tả thì cứ yêu cầu làm luôn.&lt;/p&gt;
&lt;p&gt;Tài liệu cũng khuyên viết yêu cầu thật cụ thể (chỉ rõ tệp, tình huống, mẫu có sẵn trong dự án) và cấu hình môi trường hợp lý: tệp &lt;code&gt;CLAUDE.md&lt;/code&gt; ngắn gọn chứa lệnh, quy ước và lưu ý riêng của dự án; danh sách quyền được phép; công cụ CLI như &lt;code&gt;gh&lt;/code&gt;; MCP server; hook cho những việc bắt buộc; skill và subagent cho kiến thức chuyên biệt. Trong phiên làm việc, hãy sửa hướng sớm, dùng &lt;code&gt;/clear&lt;/code&gt; giữa các tác vụ không liên quan, giao việc tìm hiểu cho subagent để giữ ngữ cảnh sạch. Khi đã thành thạo, có thể mở rộng bằng chế độ không tương tác &lt;code&gt;claude -p&lt;/code&gt;, chạy nhiều phiên song song và thêm bước review độc lập trước khi coi là xong.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="openai-windsurf-and-the-future-of-work"&gt;&lt;a class="link" href="https://www.subtle.so/openai-windsurf-and-the-future-of-ai-workspaces.html" target="_blank" rel="noopener"
&gt;OpenAI, Windsurf, and the future of work&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết trên Subtle phân tích tin OpenAI muốn mua Windsurf với giá khoảng 3 tỷ USD, sau khi từng nhắm tới Cursor. Về mặt kỹ thuật, tính năng cốt lõi của Windsurf (một bản fork của VS Code kèm AI agent và gợi ý mã nguồn) không quá khó xây dựng, nên giá trị thật nằm ở chỗ khác: những công cụ này có thể trở thành không gian làm việc AI cho cả những việc ngoài lập trình. Chúng cho AI quyền thao tác trực tiếp trên tệp và thư mục, hỗ trợ viết lách, nghiên cứu, quản lý nội dung, lại có sẵn Git để theo dõi phiên bản - điều mà các công cụ năng suất truyền thống chưa làm được. Ví dụ, The Pragmatic Engineer đã nối Windsurf với cơ sở dữ liệu PostgreSQL để hỏi về số liệu kinh doanh bằng ngôn ngữ tự nhiên. Tác giả so sánh xu hướng này với cách IRC từ một công cụ ngách trở thành Slack trị giá 27 tỷ USD.&lt;/p&gt;
&lt;p&gt;Ngoài ra, dữ liệu tương tác từ hàng triệu lượt sử dụng Windsurf là nguồn tín hiệu huấn luyện quý giá, có thể giúp mô hình của OpenAI bắt kịp Anthropic trên các bài đánh giá về lập trình. Bức tranh cạnh tranh cũng khá rối: Microsoft sở hữu cả VS Code lẫn GitHub Copilot và đồng thời đầu tư vào OpenAI, trong khi quỹ đầu tư của OpenAI lại rót vốn vào Cursor. Điều đó cho thấy thị trường công cụ phát triển dùng AI đang hợp nhất rất nhanh và được kỳ vọng sinh lời lớn.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="vibe-coding-is-not-an-excuse-for-low-quality-work"&gt;&lt;a class="link" href="https://addyo.substack.com/p/vibe-coding-is-not-an-excuse-for" target="_blank" rel="noopener"
&gt;Vibe Coding is Not an Excuse for Low-Quality Work&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Addy Osmani lập luận rằng lập trình với AI theo cảm hứng (&amp;ldquo;vibe coding&amp;rdquo;) là công cụ tăng tốc hữu ích, nhưng không phải lý do để bỏ qua sự chặt chẽ của kỹ thuật phần mềm. AI có thể sinh ra rất nhiều mã nguồn trong thời gian ngắn, song số lượng không đồng nghĩa với chất lượng: các dự án làm theo kiểu này thường thiếu xử lý lỗi, bỏ sót vấn đề bảo mật, khó bảo trì và dễ sụp như &amp;ldquo;nhà xếp bằng bài&amp;rdquo;. Như tác giả viết, tốc độ chẳng có nghĩa gì nếu bánh xe rời ra giữa đường, vì nợ kỹ thuật sẽ tích tụ nhanh khi không ai giám sát.&lt;/p&gt;
&lt;p&gt;Cách tiếp cận được đề xuất là coi AI như một lập trình viên junior làm việc cực nhanh: con người vẫn phải review mọi kết quả, tái cấu trúc khi cần, bổ sung xử lý trường hợp biên và viết kiểm thử đầy đủ. Tác giả đưa ra các nguyên tắc: luôn review mã nguồn do AI sinh ra, áp dụng chuẩn viết mã, dùng AI để tăng tốc chứ không để nó ra quyết định, ưu tiên kiểm thử, lặp và tinh chỉnh, nhận ra lúc nên tự viết tay, và ghi tài liệu cẩn thận. Vibe coding phát huy tốt khi làm nguyên mẫu nhanh, viết script dùng một lần, học công nghệ mới hay sinh mã khuôn mẫu, nhưng không phù hợp với hệ thống doanh nghiệp, phần mềm quan trọng hay dự án cần bảo trì lâu dài. Đó cũng là lý do kỹ sư có kinh nghiệm thường khai thác AI hiệu quả hơn, vì họ đủ hiểu biết để sửa và cải thiện gợi ý của nó.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="event-hidden-architectures"&gt;&lt;a class="link" href="https://skiplabs.io/blog/event-hidden-arch" target="_blank" rel="noopener"
&gt;Event-Hidden Architectures&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Charles Zedlewski, cố vấn của SkipLabs, cho rằng kiến trúc hướng sự kiện (event-driven) - vốn được xem là lựa chọn bắt buộc cho ứng dụng phân tán trên cloud - đã lỗi thời, và đề xuất thay bằng kiến trúc &amp;ldquo;ẩn sự kiện&amp;rdquo; (event-hidden). Ứng dụng phân tán vẫn sẽ tồn tại, nhưng việc để lập trình viên tự quản lý sự kiện gây ra nhiều khó khăn: phải xử lý luồng bất đồng bộ phức tạp, duy trì hàng đợi và schema, và gỡ lỗi xuyên qua nhiều hệ thống. Theo tác giả, sự phức tạp này từng là cái giá cần thiết vào khoảng năm 2020, nhưng giờ không còn bắt buộc nữa.&lt;/p&gt;
&lt;p&gt;Ba nhóm công nghệ giúp điều đó trở nên khả thi: ở frontend là React cùng các thư viện quản lý trạng thái; ở phía ghi dữ liệu của backend là các hệ thống thực thi bền vững (durable execution) như Temporal, Restate, DBOS, đảm bảo tính đúng đắn khi đi qua ranh giới giữa các service; ở phía đọc dữ liệu là các framework phản ứng như Skip để tổng hợp dữ liệu phân tán hiệu quả. Điểm chung của chúng là che đi chi tiết hạ tầng, xử lý phần bất đồng bộ một cách trong suốt và coi trạng thái là mối quan tâm hàng đầu. Nhờ vậy, lập trình viên viết mã nguồn đơn giản, dễ bảo trì hơn, đồng thời có thêm lợi ích như dễ quan sát, quản lý trạng thái tốt hơn và có thể phát lại hoạt động của ứng dụng. Tác giả dự đoán kiến trúc ẩn sự kiện sẽ trở thành kiến trúc mặc định cho ứng dụng web trong 10 năm tới.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="lessons-from-distributed-systems"&gt;&lt;del&gt;&lt;a class="link" href="https://www.16elt.com/2025/04/19/lessons-from-distributed-systems/" target="_blank" rel="noopener"
&gt;Lessons from Distributed Systems&lt;/a&gt;&lt;/del&gt;
&lt;/h2&gt;&lt;p&gt;&lt;del&gt;Bài viết từ 16elt.com chia sẻ những bài học thực tế từ việc xây dựng và vận hành distributed systems ở quy mô lớn. Tác giả tổng hợp những kinh nghiệm xương máu về các vấn đề thường gặp và cách giải quyết khi làm việc với hệ thống phân tán.&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/del&gt;
&lt;del&gt;- Tách riêng cache clusters: tránh chia sẻ một cache cluster cho nhiều services vì workload nặng từ Service A có thể evict dữ liệu quan trọng của Service B, gây ra performance issues khó chẩn đoán&lt;/del&gt;
&lt;del&gt;- Sử dụng message queues: queues giúp quản lý traffic spikes và service load, cung cấp buffering và resilience giữa các services như &amp;ldquo;một người trưởng thành có trách nhiệm&amp;rdquo; ngăn chặn service overload&lt;/del&gt;
&lt;del&gt;- Đo lường end-to-end latency: không chỉ xem xét service response times mà còn cả &amp;ldquo;dequeue latency&amp;rdquo; - thời gian messages chờ trong queue trước khi được xử lý&lt;/del&gt;
&lt;del&gt;- Design for failure: expect và plan cho network và service failures tiềm tàng, implement retry policies, circuit breakers, dead-letter queues cho failed messages&lt;/del&gt;
&lt;del&gt;- Đảm bảo idempotency: assume message duplicates sẽ xảy ra, thiết kế hệ thống handle repeated events một cách graceful vì message queues guarantee &amp;lsquo;at least once&amp;rsquo; delivery&lt;/del&gt;
&lt;del&gt;- Distributed systems đòi hỏi proactive design, robust monitoring và resilient architecture để quản lý complexity và potential failure points&lt;/del&gt;
&lt;del&gt;- Monitoring và observability là chìa khóa để hiểu được hành vi thực của hệ thống trong production environment&lt;/del&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="better-error-handling"&gt;&lt;del&gt;&lt;a class="link" href="https://meowbark.dev/Better-error-handling" target="_blank" rel="noopener"
&gt;Better error handling&lt;/a&gt;&lt;/del&gt;
&lt;/h2&gt;&lt;p&gt;&lt;del&gt;Bài viết từ meowbark.dev khám phá các phương pháp xử lý lỗi hiện đại trong software development, từ traditional try/catch cho đến các kỹ thuật tiên tiến như Go-style error handling và monadic Result types. Tác giả phân tích ưu nhược điểm của từng approach và đưa ra khuyến nghị về cách chọn lựa phương pháp phù hợp.&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/del&gt;
&lt;del&gt;- Ba approaches chính cho error handling: traditional try/catch, Go-style return tuples, và monadic Result types&lt;/del&gt;
&lt;del&gt;- Challenges của error handling truyền thống: thiếu type safety, unpredictable error control flow, limited type system integration&lt;/del&gt;
&lt;del&gt;- Go-style approach: return errors như part của tuple, explicitly handle failure scenarios, cung cấp clear error context&lt;/del&gt;
&lt;del&gt;- Monadic Result approach: treat errors as values, sử dụng container types như &lt;code&gt;Result&amp;lt;T,E&amp;gt;&lt;/code&gt;, enable functional-style error chaining&lt;/del&gt;
&lt;del&gt;- Best practices quan trọng: phân biệt recoverable và unrecoverable errors, wrap external library errors sớm, sử dụng type-safe error handling mechanisms&lt;/del&gt;
&lt;del&gt;- Cân nhắc performance và developer experience khi chọn strategy&lt;/del&gt;
&lt;del&gt;- Recommended techniques: sử dụng libraries như &lt;code&gt;neverthrow&lt;/code&gt; cho robust error management, implement error mapping và transformation&lt;/del&gt;
&lt;del&gt;- Tạo centralized error handling layers để quản lý lỗi một cách systematic&lt;/del&gt;
&lt;del&gt;- Chọn error handling strategy cân bằng giữa type safety, readability, và team expertise&lt;/del&gt;
&lt;del&gt;- Duy trì clear error communication và recovery mechanisms trong suốt application&lt;/del&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #29</title><link>https://miti99.com/post/2025/05/16/</link><pubDate>Fri, 16 May 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/05/16/</guid><description>&lt;p&gt;&lt;em&gt;Chào mừng bạn đến với Newsletter #29 - Tổng hợp tin tức công nghệ hôm nay.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="a-clean-approach-to-process-optimization"&gt;&lt;a class="link" href="https://queue.acm.org/detail.cfm?id=3722546" target="_blank" rel="noopener"
&gt;A Clean Approach to Process Optimization&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Thomas A. Limoncelli bắt đầu bài viết bằng một ví dụ rất đời thường: cách ông sắp xếp lại việc rửa bát ở nhà. Thay vì đợi đến lúc bắt đầu chu kỳ rửa mới cho bột giặt vào máy, ông làm việc đó ngay sau khi lấy bát đĩa sạch ra. Chỉ bằng cách đổi thứ tự các bước, công việc trở nên trơn tru hơn mà không cần thêm công sức. Tác giả sau đó áp dụng đúng tư duy này vào quy trình tiếp nhận khách hàng mới tại công ty, rút thời gian chờ từ vài ngày xuống chỉ còn vài phút.&lt;/p&gt;
&lt;p&gt;Ý tưởng cốt lõi là chia quy trình thành hai giai đoạn. Giai đoạn chậm gồm những tác vụ chung, có thể làm sẵn trước khi có đơn hàng; giai đoạn nhanh chỉ xử lý phần tùy chỉnh cụ thể sau khi đơn hàng đến. Song song với đó, hãy rà soát lại các tác vụ tùy chọn, vì nhiều khi chúng không thực sự cần thiết hoặc có thể làm theo cách hiệu quả hơn. Với lập trình viên trẻ, đây là một bài học hữu ích: cách tiếp cận này áp dụng được cho quy trình triển khai phần mềm, cấp phát hạ tầng lẫn nhiều lĩnh vực khác, giúp cải thiện cả hiệu năng lẫn chất lượng dịch vụ.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="microsoft"&gt;&lt;a class="link" href="https://www.gatesnotes.com/microsoft-original-source-code" target="_blank" rel="noopener"
&gt;Microsoft&amp;rsquo;s Original Source Code Released for 50th Anniversary&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Nhân dịp Microsoft tròn 50 tuổi, Bill Gates công bố mã nguồn gốc của Altair BASIC, sản phẩm đầu tiên của công ty, và gọi đó là đoạn mã &amp;ldquo;thú vị nhất&amp;rdquo; ông từng viết. Câu chuyện bắt đầu từ trang bìa tạp chí Popular Electronics tháng 1/1975 giới thiệu máy tính Altair 8800 của hãng MITS. Gates và Paul Allen liên hệ với nhà sáng lập Ed Roberts, nói rằng họ đã có sẵn một phiên bản BASIC cho con chip của Altair, dù thực tế chưa hề viết dòng nào. Hai người chọn xây dựng một trình thông dịch (interpreter) thay vì trình biên dịch, vì cách chạy từng dòng giúp người mới học nhận phản hồi ngay và sửa lỗi dễ hơn.&lt;/p&gt;
&lt;p&gt;Do không có chip Intel 8080, Allen viết chương trình giả lập nó trên máy PDP-10 của Harvard, Gates viết phần lõi, còn Monte Davidoff đảm nhận gói xử lý toán học. Sau khoảng hai tháng làm việc ngày đêm, họ phải nén toàn bộ trình thông dịch vào chỉ 4 KB bộ nhớ bằng các cấu trúc dữ liệu gọn và thuật toán hiệu quả, vì bộ nhớ khi ấy còn đắt hơn cả chiếc máy. Buổi trình diễn thành công, MITS mua bản quyền, và Micro-Soft ra đời. Với lập trình viên hôm nay, đây là minh chứng sinh động cho việc tối ưu khi tài nguyên phần cứng cực kỳ hạn chế; chi tiết hơn được kể trong cuốn hồi ký &amp;ldquo;Source Code&amp;rdquo; của Gates.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="no-code-is-dead-long-live-vibe-coding"&gt;&lt;a class="link" href="https://kenneth.io/post/no-code-is-dead-long-live-vibe-coding" target="_blank" rel="noopener"
&gt;No code is dead. Long live vibe coding&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Kenneth Auchenberg đưa ra một nhận định thẳng thắn: năm 2025, no-code đã chết. Suốt một thập kỷ, các nền tảng no-code và low-code hứa hẹn sẽ dân chủ hóa việc tạo ra phần mềm, nhưng không nền tảng nào thực sự bứt phá hay thay thế được lập trình truyền thống. Thay vào đó, một thế hệ công cụ mới dựa trên AI và mô hình ngôn ngữ lớn đang nổi lên, gọi là &amp;ldquo;vibe coding&amp;rdquo;. Những cái tên như Bolt, Lovable hay v0 cho thấy việc viết mã nguồn thực thụ, đủ chất lượng cho môi trường production, từ mô tả bằng ngôn ngữ tự nhiên không chỉ khả thi mà còn tốt hơn các trình soạn thảo kéo-thả WYSIWYG.&lt;/p&gt;
&lt;p&gt;Theo tác giả, người dùng hóa ra không muốn &amp;ldquo;ít mã nguồn hơn&amp;rdquo;, mà muốn một cách tốt hơn để viết mã nguồn. Họ không muốn bị khóa vào môi trường chạy độc quyền; họ muốn có mã nguồn thật, toàn quyền kiểm soát, tự do chỉnh sửa và triển khai ở bất cứ đâu. Thế hệ trước như Webflow hay Retool gói trọn trình soạn thảo, hosting, môi trường chạy và thành phần giao diện trong một hệ thống đóng. Giờ đây, mô hình ngôn ngữ lớn có thể sinh mã React gọn gàng, tuân theo tiêu chuẩn mở và thực hành tốt của ngành, rồi triển khai lên hạ tầng mở. Tác giả gọi đây là sự &amp;ldquo;tháo gỡ&amp;rdquo; (unbundling) của no-code.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="simple-scalable-and-global-containers-are-coming-to-cloudflare-workers-in-june-2025"&gt;&lt;a class="link" href="https://blog.cloudflare.com/cloudflare-containers-coming-2025/" target="_blank" rel="noopener"
&gt;Simple, scalable, and global: Containers are coming to Cloudflare Workers in June 2025&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Cloudflare công bố sẽ mở bản beta công khai của Containers vào cuối tháng 6/2025. Workers vốn là cách đơn giản nhất để đưa phần mềm ra toàn cầu, nhưng có những việc chúng không đảm đương được: chạy mã do người dùng tạo ra bằng bất kỳ ngôn ngữ nào, chạy công cụ dòng lệnh cần môi trường Linux đầy đủ, dùng nhiều GB bộ nhớ hay nhiều nhân CPU, hoặc chuyển ứng dụng từ AWS, GCP, Azure sang mà không phải viết lại. Containers ra đời để lấp khoảng trống đó. Chỉ với vài dòng cấu hình Wrangler và lệnh &lt;code&gt;wrangler deploy&lt;/code&gt;, container được khởi động theo yêu cầu tại vị trí gần người dùng nhất, tự ngủ sau thời gian chờ có thể cấu hình, và hỗ trợ tự động mở rộng theo mức sử dụng CPU.&lt;/p&gt;
&lt;p&gt;Điểm khác biệt nằm ở kiến trúc: mỗi container được quản lý bởi một Durable Object đóng vai trò &amp;ldquo;sidecar&amp;rdquo; lập trình được, cho phép khởi động, dừng, chạy lệnh và theo dõi trạng thái container ngay trong mã nguồn. Nhờ vậy, Workers có thể làm API Gateway, Service Mesh hoặc bộ điều phối cho các container mà không cần viết Kubernetes operator hay cấu hình control plane phức tạp. Về chi phí, người dùng chỉ trả tiền cho thời gian container thực sự chạy, với mức giá tính theo vCPU, bộ nhớ và ổ đĩa mà Cloudflare so sánh là cạnh tranh với Google Cloud Run. Bài học rút ra: hãy xử lý phần lớn yêu cầu bằng Workers nhẹ và rẻ, chỉ dùng container cho những tác vụ nặng thực sự cần đến.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="the-types-of-companies-you-can-work-for-and-what-they-do-for-your-career"&gt;&lt;a class="link" href="https://www.elenaverna.com/p/the-types-of-companies-you-can-work" target="_blank" rel="noopener"
&gt;The types of companies you can work for and what they do for your career&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Elena Verna khuyên nên chọn nơi làm việc có chủ đích thay vì chạy theo chức danh hay mức lương. Bà chia công ty thành sáu kiểu. &amp;ldquo;Kỳ lân&amp;rdquo; (Unicorns) là các công ty tăng trưởng khoảng 100% mỗi năm như Miro hay Figma thời đầu: tốc độ chóng mặt, dễ kiệt sức, nhưng kinh nghiệm ở đây mở ra rất nhiều cánh cửa. &amp;ldquo;Tàu chở dầu&amp;rdquo; (Tankers) như Google, Apple, Microsoft vận hành bài bản, lương cao, nhiều tài nguyên đào tạo, rất hợp để bắt đầu sự nghiệp, dù vai trò chuyên biệt hóa cao và tiến độ chậm. &amp;ldquo;Người khổng lồ suy thoái&amp;rdquo; (Declining Giants) liên tục tái cơ cấu; áp lực kết quả lớn nhưng cơ hội thăng tiến nhanh. &amp;ldquo;Chế độ sinh tồn&amp;rdquo; (Survival Mode) là các startup chưa tìm ra sản phẩm phù hợp thị trường: tự chủ cao, kỹ năng rộng, nhưng rủi ro lớn và tác giả không khuyên người mới vào nghề chọn.&lt;/p&gt;
&lt;p&gt;Hai kiểu còn lại là &amp;ldquo;Công ty lối sống&amp;rdquo; (Lifestyle Boats), thường tự chủ tài chính, có lãi và tăng trưởng bền vững như Basecamp, rất tốt cho người mới nhờ môi trường có hỗ trợ; và &amp;ldquo;Hướng tới xã hội&amp;rdquo; (Social Good Seekers), nơi tác động xã hội được đặt trên doanh thu, lương có thể thấp hơn nhưng sự hài lòng cao. Để nhận diện một công ty, hãy hỏi về số nhân sự, tốc độ tăng trưởng doanh thu ba năm gần nhất và công ty còn bao lâu trước khi phải gọi vốn tiếp. Đồng thời, hãy tự hỏi mình chịu được bao nhiêu thay đổi và áp lực, có cần vai trò rõ ràng không, và ưu tiên tài chính hiện tại là gì.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="how-to-create-a-chain-reaction-of-good-habits"&gt;&lt;a class="link" href="https://jamesclear.com/domino-effect" target="_blank" rel="noopener"
&gt;How to Create a Chain Reaction of Good Habits&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;James Clear, tác giả cuốn &amp;ldquo;Atomic Habits&amp;rdquo;, giải thích Hiệu ứng Domino: khi bạn thay đổi một hành vi, nó sẽ kích hoạt chuỗi phản ứng làm thay đổi cả những hành vi liên quan. Ông kể câu chuyện của Jennifer Dukes Lee, người suốt hơn hai mươi năm không dọn giường; sau bốn ngày liên tiếp làm việc đó, bà tiện tay gấp quần áo, rửa bát rồi sắp xếp lại tủ bếp. Một nghiên cứu năm 2012 của Đại học Northwestern cũng cho thấy khi mọi người giảm thời gian ngồi một chỗ, họ tự nhiên ăn ít chất béo hơn dù không ai yêu cầu. Hiệu ứng này đúng cả với thói quen xấu, chẳng hạn kiểm tra điện thoại dẫn đến lướt mạng xã hội rồi trì hoãn thêm hai mươi phút.&lt;/p&gt;
&lt;p&gt;Theo tác giả, hiệu ứng xảy ra vì các thói quen hằng ngày liên kết chặt chẽ với nhau, và vì nguyên tắc cam kết và nhất quán: khi đã cam kết dù rất nhỏ, ta có xu hướng giữ lời vì thấy điều đó khớp với hình ảnh bản thân. Để chủ động tạo ra chuỗi domino tốt, hãy bắt đầu bằng việc nhỏ mà bạn có động lực nhất và làm đều đặn, tận dụng đà hoàn thành một việc để chuyển ngay sang việc tiếp theo, và khi gặp khó thì chia nhỏ mọi thứ, tập trung vào tiến trình thay vì kết quả. Điều thú vị là hiệu ứng này không chỉ tạo ra hành vi mới mà còn thay đổi niềm tin: mỗi quân domino đổ xuống giúp bạn tin vào một phiên bản mới của bản thân và xây dựng thói quen dựa trên bản sắc.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="the-post-developer-era"&gt;&lt;a class="link" href="https://www.joshwcomeau.com/blog/the-post-developer-era/" target="_blank" rel="noopener"
&gt;The Post-Developer Era&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Hai năm sau bài &amp;ldquo;The End of Front-End Development&amp;rdquo; viết lúc GPT-4 ra mắt, Josh W. Comeau nhìn lại xem liệu chúng ta đã bước vào kỷ nguyên &amp;ldquo;hậu lập trình viên&amp;rdquo; chưa. Câu trả lời là chưa. Con số &amp;ldquo;AI viết hơn 25% mã nguồn tại Google&amp;rdquo; dễ gây hiểu lầm, vì AI không làm việc độc lập mà luôn có lập trình viên giỏi cầm lái, định hướng và chỉnh sửa. Còn Devin, công cụ tự nhận có thể thay thế lập trình viên, chỉ hoàn thành 3 trên 20 nhiệm vụ khi một nhóm thử nghiệm thực tế. Tác giả dùng Cursor với Claude Sonnet và thấy nó rất ấn tượng, nhưng ví nó như chế độ ga tự động: nếu buông tay lái, xe sẽ dần trôi khỏi làn. Người không biết lập trình sẽ không nhận ra những lỗi tinh vi và cuối cùng bị kẹt với một mớ mã nguồn khó bảo trì.&lt;/p&gt;
&lt;p&gt;Thị trường việc làm vẫn khó khăn, nhưng theo tác giả nguyên nhân chủ yếu là lãi suất cao, làn sóng sa thải ở các công ty lớn và niềm tin sai rằng AI sắp khiến lập trình viên trở nên thừa thãi, chứ không phải AI đã thực sự thay thế con người. Ông cũng lo ngại thế hệ mới dễ sa vào &amp;ldquo;vibe coding&amp;rdquo;, liên tục bấm chấp nhận thay đổi mà không hiểu mã nguồn. Ngược lại, nếu dùng AI chủ động như một gia sư riêng, đây là thời điểm tốt nhất để học lập trình, và một &amp;ldquo;thời kỳ phục hưng&amp;rdquo; cho lập trình viên sẽ đến khi các công ty nhận ra AI là công cụ tăng sức mạnh chứ không phải thay thế.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="everything-wrong-with-model-context-protocol-mcp"&gt;&lt;a class="link" href="https://blog.sshh.io/p/everything-wrong-with-mcp" target="_blank" rel="noopener"
&gt;Everything Wrong With Model Context Protocol (MCP)&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Shrivu Shankar phân tích những lỗ hổng và hạn chế của Model Context Protocol, tiêu chuẩn để kết nối công cụ và dữ liệu bên thứ ba với các trợ lý AI như Claude, ChatGPT hay Cursor. Về bảo mật giao thức, phiên bản đầu không định nghĩa cơ chế xác thực và bản đặc tả sau đó lại bị chê phức tạp; máy chủ MCP chạy cục bộ qua stdio tạo đường tắt để người dùng ít kinh nghiệm tải và chạy mã độc; nhiều máy chủ còn tin tưởng đầu vào và thực thi luôn. Về trải nghiệm, MCP không phân biệt mức độ rủi ro giữa công cụ đọc nhật ký và công cụ xóa tệp, không kiểm soát chi phí token, và chỉ trả về dữ liệu không có cấu trúc.&lt;/p&gt;
&lt;p&gt;Nghiêm trọng hơn là bảo mật của chính mô hình ngôn ngữ. Mô tả công cụ thường được đưa vào system prompt nên có quyền lớn để chi phối agent; máy chủ có thể âm thầm đổi tên và mô tả công cụ sau khi người dùng đã chấp thuận, và dữ liệu kéo về từ bên thứ tư, như một dòng trong cơ sở dữ liệu, có thể chứa prompt injection. Việc tổng hợp dữ liệu dễ dàng còn giúp nhân viên suy ra thông tin nhạy cảm từ những gì vốn được phép xem. Cuối cùng, độ tin cậy của mô hình giảm khi có quá nhiều công cụ, và bộ công cụ đơn giản kiểu liệt kê hay đọc tệp không đủ cho những truy vấn mà người dùng kỳ vọng. Tác giả kết luận rằng cần cùng lúc một giao thức an toàn mặc định, ứng dụng biết bảo vệ người dùng và người dùng hiểu rõ lựa chọn của mình.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #20</title><link>https://miti99.com/post/2025/05/07/</link><pubDate>Wed, 07 May 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/05/07/</guid><description>&lt;p&gt;&lt;em&gt;Mời bạn thưởng thức Newsletter #20.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="performance-improvements-in-jdk-24"&gt;&lt;a class="link" href="https://inside.java/2025/03/19/performance-improvements-in-jdk24/" target="_blank" rel="noopener"
&gt;Performance Improvements in JDK 24&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết trên Inside.java tổng hợp những cải tiến hiệu năng đáng chú ý nhất của JDK 24 so với JDK 23, liệt kê theo từng mục trong hệ thống theo dõi lỗi của JDK. Ở nhóm thư viện lõi, các thao tác hàng loạt của Foreign Function &amp;amp; Memory API như &lt;code&gt;MemorySegment::fill&lt;/code&gt;, &lt;code&gt;copy&lt;/code&gt; và &lt;code&gt;mismatch&lt;/code&gt; giờ được xử lý bằng mã Java thuần khi vùng nhớ đủ nhỏ, tránh chi phí chuyển sang mã native qua Unsafe. Việc nối chuỗi chuyển sang dùng các lớp ẩn (hidden class) có thể lưu đệm và tái sử dụng thay vì dựng nhiều &lt;code&gt;MethodHandle&lt;/code&gt; trung gian; các thuật toán SHA3 nhanh hơn tới 27% nhờ giảm chuyển đổi giữa mảng byte và mảng long; còn quá trình chuyển sang ClassFile API được tối ưu để giảm ảnh hưởng tới thời gian khởi động.&lt;/p&gt;
&lt;p&gt;Ở tầng runtime, JEP 491 cho phép virtual thread bị chặn trong khối &lt;code&gt;synchronized&lt;/code&gt; nhả luồng mang (carrier thread) thay vì bị ghim cố định, giúp mã dùng &lt;code&gt;synchronized&lt;/code&gt; mở rộng tốt hơn. &lt;code&gt;String::indexOf&lt;/code&gt; nhanh hơn khoảng 1,3 lần trên nền tảng x64 hỗ trợ AVX2. JEP 483 (Ahead-of-Time Class Loading &amp;amp; Linking), sản phẩm đầu tiên của Project Leyden, dùng bộ nhớ đệm AOT để cải thiện thời gian khởi động khoảng 42% trong ví dụ của bài. JEP 450 thử nghiệm header đối tượng chỉ 8 byte, giúp giảm 10–20% bộ nhớ với các khối lượng công việc thông thường. Ngoài ra, nền tảng RISC-V cũng nhận thêm nhiều hàm intrinsic như CRC32, Adler32 cùng các tối ưu cho so sánh chuỗi và đảo byte.&lt;/p&gt;
&lt;h2 id="clean-your-memory-from-finalize-to-cleaner"&gt;&lt;a class="link" href="https://blog.frankel.ch/java-cleaner/" target="_blank" rel="noopener"
&gt;Clean your Memory: From Finalize to Cleaner&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Stefano Fago giải thích rằng bộ thu gom rác (GC) của Java chỉ quản lý bộ nhớ, không tự giải phóng các tài nguyên bên ngoài như socket hay file handle; nếu quản lý sai, ứng dụng có thể rò rỉ tài nguyên, chậm dần hoặc sập. Cách cũ là ghi đè &lt;code&gt;finalize()&lt;/code&gt;, nhưng phương thức này đã bị đánh dấu lỗi thời vì thời điểm chạy không đoán trước được, đối tượng phải qua thêm một chu kỳ GC mới được thu hồi, có thể gây rò rỉ nếu đối tượng vô tình bị giữ lại, và luồng Finalizer riêng dễ gây tranh chấp. Giải pháp thay thế là Cleaner API, có từ Java 9: bên dưới nó dùng &lt;code&gt;PhantomReference&lt;/code&gt; cùng một luồng daemon nền, nhưng che giấu sự phức tạp của các lớp Reference. Bạn đăng ký đối tượng kèm một hành động dọn dẹp, và khi đối tượng không còn truy cập được, hành động đó được đưa vào hàng đợi để chạy trên luồng nền.&lt;/p&gt;
&lt;p&gt;Cleaner có thể kết hợp với &lt;code&gt;AutoCloseable&lt;/code&gt;: phương thức &lt;code&gt;close()&lt;/code&gt; gọi &lt;code&gt;clean()&lt;/code&gt; để dọn dẹp ngay khi cần, còn Cleaner đóng vai trò lưới an toàn. Tuy vậy, tác giả nhấn mạnh chỉ nên dùng Cleaner khi không thể giải phóng tài nguyên bằng try-with-resources hoặc gọi &lt;code&gt;close()&lt;/code&gt; tường minh, vì cơ chế này dọn dẹp bất đồng bộ và tốn chi phí hơn do cần luồng nền. Khi viết hành động dọn dẹp, nên tránh lambda vì dễ vô tình giữ tham chiếu tới chính đối tượng cần dọn, khiến nó không bao giờ được thu hồi; hành động cũng cần ngắn gọn và không chặn, vì nhiều hành động có thể chạy đồng thời trên cùng một Cleaner.&lt;/p&gt;
&lt;h2 id="5-hidden-git-tips-for-java-developers"&gt;&lt;a class="link" href="https://www.azul.com/blog/5-hidden-git-tips-for-java-developers/" target="_blank" rel="noopener"
&gt;5 Hidden Git Tips for Java Developers&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Trên blog của Azul, Luqman Saeed giới thiệu năm tính năng ít được chú ý của Git, vượt ra ngoài bộ ba quen thuộc commit, push và pull, kèm ví dụ gắn với dự án Java. Đầu tiên là &lt;code&gt;git bisect&lt;/code&gt;: khi không rõ commit nào gây lỗi, bạn đánh dấu commit hiện tại là xấu (&lt;code&gt;git bisect bad&lt;/code&gt;) và một commit cũ còn chạy đúng là tốt (&lt;code&gt;git bisect good &amp;lt;commit-hash&amp;gt;&lt;/code&gt;), rồi Git tìm kiếm nhị phân bằng cách lần lượt checkout commit ở giữa để bạn kiểm thử cho đến khi tìm ra thủ phạm; kết thúc bằng &lt;code&gt;git bisect reset&lt;/code&gt;. Tiếp theo, &lt;code&gt;git blame &amp;lt;tên-tệp&amp;gt;&lt;/code&gt; cho biết ai sửa từng dòng lần cuối và vào lúc nào (thêm cờ &lt;code&gt;-L 50,60&lt;/code&gt; để chỉ xem một đoạn), giúp bạn hiểu bối cảnh trước khi gỡ lỗi hay tái cấu trúc. Khi phải chuyển việc giữa chừng, &lt;code&gt;git stash&lt;/code&gt; cất tạm các thay đổi chưa commit và &lt;code&gt;git stash pop&lt;/code&gt; lấy chúng lại; &lt;code&gt;git stash list&lt;/code&gt; cùng &lt;code&gt;git stash apply &amp;lt;stash-id&amp;gt;&lt;/code&gt; giúp quản lý nhiều lần cất.&lt;/p&gt;
&lt;p&gt;Với các tệp tạm do Maven hay Gradle sinh ra như &lt;code&gt;.class&lt;/code&gt; hoặc thư mục &lt;code&gt;target/&lt;/code&gt;, &lt;code&gt;git clean -n&lt;/code&gt; cho xem trước, &lt;code&gt;-f&lt;/code&gt; xóa tệp chưa theo dõi, &lt;code&gt;-fd&lt;/code&gt; xóa cả thư mục, còn &lt;code&gt;-x&lt;/code&gt; xóa luôn các tệp bị bỏ qua như &lt;code&gt;.idea/&lt;/code&gt;. Cuối cùng, git hooks là các script tự chạy trước hoặc sau những sự kiện như commit, push hay merge; chẳng hạn một hook &lt;code&gt;pre-commit&lt;/code&gt; đặt trong &lt;code&gt;.git/hooks&lt;/code&gt; có thể chạy &lt;code&gt;mvn test&lt;/code&gt; và hủy commit nếu kiểm thử thất bại. Mẹo bổ sung: &lt;code&gt;git checkout -&lt;/code&gt; đưa bạn về nhánh vừa làm việc trước đó mà không cần gõ lại tên nhánh, vừa tiết kiệm thời gian vừa tránh gõ sai.&lt;/p&gt;
&lt;h2 id="simplify-your-system-by-challenging-the-status-quo-and-learning-from-other-ecosystems"&gt;&lt;a class="link" href="https://www.infoq.com/podcasts/simplify-system-learning-ecosystems/" target="_blank" rel="noopener"
&gt;Simplify Your System by Challenging the Status-Quo and Learning from Other Ecosystems&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Trong podcast của InfoQ, Max Rydahl Andersen, Distinguished Engineer tại Red Hat và tác giả của JBang, kể rằng sau một năm tạm rời Java, khi quay lại ông nhận ra cộng đồng đã tích tụ quá nhiều độ phức tạp, giống như &amp;ldquo;một nghìn vết cắt giấy&amp;rdquo; (thousand paper cuts): mỗi tính năng nhỏ đều hữu ích nhưng cộng lại thành gánh nặng. Quarkus, dự án ông tham gia, đảo ngược cách làm truyền thống bằng cách dời phần lớn xử lý sang thời điểm build thay vì runtime, nhờ đó ứng dụng khởi động rất nhanh. Tốc độ này còn mở ra trải nghiệm phát triển tốt hơn: tải lại nóng (hot reload), kiểm thử liên tục, Dev Services tự dựng các dịch vụ như PostgreSQL hay Kafka, và giao diện chat để thử dịch vụ AI qua LangChain4J ngay trong Dev UI.&lt;/p&gt;
&lt;p&gt;Với JBang, ông lấy cảm hứng từ Python và Node.js để chạy Java chỉ từ một tệp duy nhất, thậm chí tự tải JDK nếu máy chưa cài; ông tuyên bố nếu tìm được môi trường phát triển nào dễ cài đặt hơn thì đó là lỗi của JBang. Max cũng cho rằng AI không thay thế được nền tảng kỹ thuật phần mềm và tư duy hệ thống, đồng thời cảnh báo AI sẽ giúp khai thác lỗ hổng (CVE) nhanh hơn, nên các hệ thống cũ cần được cập nhật thường xuyên hơn. Thông điệp chung của buổi trò chuyện: hãy thách thức hiện trạng và học hỏi từ các hệ sinh thái khác để giữ hệ thống đơn giản.&lt;/p&gt;
&lt;h2 id="about"&gt;&lt;a class="link" href="https://tryingthings.wordpress.com/2025/03/24/about-vibe-coding/" target="_blank" rel="noopener"
&gt;About &amp;ldquo;vibe coding&amp;rdquo;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Sorin Costea viết ngắn gọn về trào lưu &amp;ldquo;vibe coding&amp;rdquo;, tức để AI viết mã nguồn thay cho lập trình viên. Sau khi đọc bài &amp;ldquo;Vibe coding vs Reality&amp;rdquo;, ông thấy không chỉ riêng ông hoài nghi, vì chính ông đã thử Cursor với một dự án Java Maven và công cụ này thậm chí không đổi tên nổi một lớp: lúc thì chỉ đổi tên lớp mà không đổi tên tệp, lúc được yêu cầu lại thì tạo ra một tệp rỗng mang tên mới, và chuyện đó lặp lại hai lần.&lt;/p&gt;
&lt;p&gt;Khi chia sẻ trên Hacker News, ông chỉ nhận được những phản hồi kiểu &amp;ldquo;haha Java&amp;rdquo;, khiến ông tự hỏi Cursor chỉ được huấn luyện cho các framework frontend thịnh hành hay những người ủng hộ nó không quan tâm đến ứng dụng thực tế. Kết quả là ông gỡ Cursor và càng hoài nghi các giải pháp AI &amp;ldquo;thần kỳ&amp;rdquo;, dù vẫn để ngỏ khả năng thay đổi: &amp;ldquo;Nhưng năm sau? Năm sau sẽ biết.&amp;rdquo;&lt;/p&gt;
&lt;h2 id="visual-focused-algorithms-cheat-sheet"&gt;&lt;a class="link" href="https://photonlines.substack.com/p/visual-focused-algorithms-cheat-sheet" target="_blank" rel="noopener"
&gt;Visual-Focused Algorithms Cheat Sheet&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Nick M tổng hợp một bảng tra cứu (cheat sheet) thiên về hình ảnh cho các thuật toán quan trọng được dùng trong thực tế, nối tiếp bảng tra cứu cấu trúc dữ liệu trước đó của ông; mỗi thuật toán được giải thích bằng ví dụ đời thường và hình minh họa. Phần sắp xếp đi từ Selection Sort và Insertion Sort, đơn giản nhưng có độ phức tạp O(n²), đến Heap Sort, Quick Sort và Merge Sort với O(n log n), rồi Tim Sort, thuật toán lai giữa Insertion Sort và Merge Sort được dùng trong Python và Java. Phần tìm kiếm gồm Binary Search với O(log n) cùng DFS và BFS để duyệt đồ thị theo chiều sâu và chiều rộng. Phần đồ thị trình bày Prim và Kruskal để tìm cây khung nhỏ nhất, Dijkstra và Bellman-Ford để tìm đường đi ngắn nhất (Bellman-Ford xử lý được cả trọng số âm), A* dùng hàm ước lượng (heuristic), cùng Union-Find và Ford-Fulkerson.&lt;/p&gt;
&lt;p&gt;Các phần tiếp theo bao quát tìm kiếm chuỗi, nén và mã hóa dữ liệu (Huffman, LZ, biến đổi Fourier, nén ảnh JPEG), tối ưu hóa (Simplex, Simulated Annealing), học máy và khoa học dữ liệu, cùng các thuật toán bảo mật và mật mã. Cuối bài là mục tài liệu luyện phỏng vấn như &amp;ldquo;14 Patterns to Ace Any Coding Interview&amp;rdquo; và &amp;ldquo;5 Simple Steps for Solving Dynamic Programming Problems&amp;rdquo;, rất hữu ích cho các bạn mới vào nghề đang chuẩn bị phỏng vấn.&lt;/p&gt;
&lt;h2 id="bonus-vài-ảnh-hay-ho-đến-từ-bytebytego"&gt;Bonus: Vài ảnh hay ho đến từ &lt;a class="link" href="https://bytebytego.com/" target="_blank" rel="noopener"
&gt;ByteByteGo&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/81074d22-5821-4aec-bb2d-0a099d06b6ac_1600x840.png"
loading="lazy"
alt="3 Steps to Master Your Software"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/67c39b9a-9a91-4e57-9e24-7714b4f806dd_1280x1349.gif"
loading="lazy"
alt="The Ultimate Software Architect Roadmap"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/fb1b1cd1-eac3-4b66-a391-9ec73f6c37f3_1280x1502.gif"
loading="lazy"
alt="How Two-factor Authentication (2FA) Works?"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/3efae3ad-8c45-4fb2-a79f-6b3387b0751e_1280x1601.gif"
loading="lazy"
alt="How Amazon S3 Works?"
&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #17</title><link>https://miti99.com/post/2025/05/04/</link><pubDate>Sun, 04 May 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/05/04/</guid><description>&lt;p&gt;&lt;em&gt;Mời bạn thưởng thức Newsletter #17.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="to-fork-or-not-to-fork"&gt;&lt;a class="link" href="https://www.augmentcode.com/blog/to-fork-or-not-to-fork" target="_blank" rel="noopener"
&gt;To fork or not to fork?&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Scott Dietzen, CEO của Augment Code (từng là CEO của Pure Storage), bàn về một quyết định kiến trúc quan trọng của các trợ lý lập trình AI: chạy dưới dạng plugin trong IDE tiêu chuẩn hay fork hẳn VS Code. GitHub Copilot và Augment chọn cách thứ nhất, hoạt động như plugin trong VS Code, JetBrains hay Vim. Cursor và Windsurf (của Codeium) chọn cách thứ hai, sửa trực tiếp mã nguồn VS Code để tích hợp AI sâu hơn.&lt;/p&gt;
&lt;p&gt;Theo tác giả, fork mang lại lợi thế ngắn hạn nhưng người dùng phải trả giá: buộc phải rời IDE quen thuộc (đặc biệt thiệt thòi với người dùng JetBrains), không còn được Microsoft hỗ trợ, các plugin chính thức như Python, C++, Docker hay Jupyter có thể trục trặc, mất quyền truy cập kho tiện ích mở rộng của VS Code và phải chờ bên fork chuyển các tính năng mới sang. Vì lợi ích lâu dài của khách hàng, Augment chọn hướng plugin và tập trung vào thế mạnh hỗ trợ các dự án có mã nguồn lớn, phức tạp. Tác giả cũng cho biết Cursor là IDE phổ biến thứ ba mà người dùng chọn khi dùng thử Augment, cho thấy hai sản phẩm có thể bổ trợ cho nhau.&lt;/p&gt;
&lt;h2 id="why-i"&gt;&lt;a class="link" href="https://blog.container-solutions.com/why-im-no-longer-talking-to-architects-about-microservices" target="_blank" rel="noopener"
&gt;Why I&amp;rsquo;m No Longer Talking to Architects About Microservices&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Ian Miell giải thích vì sao anh không còn muốn bàn về microservices với các kiến trúc sư phần mềm. Vấn đề đầu tiên là không ai thống nhất microservices nghĩa là gì: có người đo bằng số dòng mã, có người gắn với cấu trúc đội ngũ, có người lại hiểu là cách triển khai bằng container. Giống như DevOps hay Agile, thuật ngữ này đã mất dần ý nghĩa ban đầu vì bị dùng quá nhiều.&lt;/p&gt;
&lt;p&gt;Vấn đề thứ hai là các cuộc trao đổi thường trừu tượng, tách rời mục tiêu kinh doanh: những lời hứa về khả năng mở rộng, sự linh hoạt hay giảm tải nhận thức hiếm khi được kiểm chứng. Vấn đề thứ ba là microservices chỉ phát huy tác dụng khi tổ chức thay đổi theo, với đội ngũ đa chức năng, quyền quyết định phân tán và văn hóa DevOps trưởng thành, mà thay đổi cơ cấu tổ chức khó hơn nhiều so với thay đổi kiến trúc. Ngay cả Sam Newman cũng khuyên đa số tổ chức không nên áp dụng microservices nếu thiếu lý do thuyết phục. Tác giả đề xuất bắt đầu từ vấn đề cụ thể như rút ngắn chu kỳ phát triển, tăng độ tin cậy hay gỡ bỏ điểm nghẽn, rồi mới xem microservices có phải là giải pháp hay không.&lt;/p&gt;
&lt;h2 id="not-all-ai-assisted-programming-is-vibe-coding-but-vibe-coding-rocks"&gt;&lt;a class="link" href="https://simonwillison.net/2025/Mar/19/vibe-coding/" target="_blank" rel="noopener"
&gt;Not all AI-assisted programming is vibe coding (but vibe coding rocks)&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Simon Willison cho rằng thuật ngữ &amp;ldquo;vibe coding&amp;rdquo;, do Andrej Karpathy đặt ra vào tháng 2/2025, đang bị dùng sai để chỉ mọi hình thức lập trình có AI hỗ trợ. Theo định nghĩa gốc, vibe coding là &amp;ldquo;quên đi sự tồn tại của mã nguồn&amp;rdquo;: chấp nhận mọi thay đổi do mô hình ngôn ngữ lớn (LLM) sinh ra mà không đọc lại. Ngược lại, lập trình có trách nhiệm với sự trợ giúp của AI vẫn bao gồm rà soát, kiểm thử và hiểu rõ từng chi tiết triển khai. Quy tắc vàng của tác giả: không đưa mã nguồn nào vào kho nếu không thể giải thích chính xác cho người khác nó làm gì.&lt;/p&gt;
&lt;p&gt;Dù vậy, Simon vẫn ủng hộ vibe coding. Nó hạ thấp rào cản cho người mới, giúp họ tự tay tạo ra những công cụ hữu ích, và là cách tốt để xây dựng trực giác về khả năng lẫn giới hạn của LLM. Điều quan trọng là chỉ áp dụng cho các dự án rủi ro thấp, dùng xong có thể bỏ, tốt nhất trong môi trường cách ly (sandbox) như Claude Artifacts, và tránh những trường hợp liên quan đến bảo mật, quyền riêng tư hay chi phí tài chính. Ông cũng mong có thêm công cụ an toàn hơn để người mới thử nghiệm mà không gây hại.&lt;/p&gt;
&lt;h2 id="career-advice-in-2025"&gt;&lt;a class="link" href="https://lethain.com/career-advice-2025" target="_blank" rel="noopener"
&gt;Career advice in 2025.&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Will Larson nhìn lại thị trường việc làm công nghệ năm 2025 và chỉ ra bốn thay đổi lớn. Thứ nhất, những nhà quản lý thăng tiến giai đoạn 2010–2020 nhờ giỏi tuyển dụng và tạo động lực nay phải đáp ứng yêu cầu mới: đi sâu vào chi tiết, đẩy nhanh tiến độ và dẫn dắt quá trình chuyển đổi sang AI. Thứ hai, làn sóng mô hình nền tảng khiến nhiều cách làm cũ mất hiệu lực; sản phẩm cần được thiết kế theo hướng xác thực dần, với dữ liệu quan trọng được con người kiểm tra (human-in-the-loop), và phải sẵn sàng cho cả kịch bản mô hình tiến bộ vượt bậc lẫn đứng yên.&lt;/p&gt;
&lt;p&gt;Thứ ba, các công ty không làm AI khó gọi vốn hơn, kéo theo ít cơ hội thăng chức và tăng lương, trong khi cổ phần ở công ty AI cũng không chắc sinh lời. Thứ tư, doanh nghiệp đang thúc ép đội ngũ hiện tại làm nhiều hơn để tìm tăng trưởng, khiến nhiều vị trí từng thoải mái trở nên áp lực. Giờ đây bạn khó có cùng lúc đồng nghiệp tốt, danh tiếng và cơ hội học hỏi. Lời khuyên của ông: đừng đứng ngoài chờ thị trường tốt lên, hãy làm cho công việc hiện tại đáng giá, và nhớ rằng khó khăn này là chung, không phản ánh năng lực cá nhân.&lt;/p&gt;
&lt;h2 id="tips-for-better-interactions"&gt;&lt;a class="link" href="https://staysaasy.com/saas/2025/03/17/interactions.html" target="_blank" rel="noopener"
&gt;Tips For Better Interactions&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Stay SaaSy đưa ra sáu lời khuyên để các cuộc họp và trao đổi nơi công sở hiệu quả hơn. Khi ai đó nói bạn đang &amp;ldquo;bực bội&amp;rdquo;, đừng chấp nhận cách gán nhãn đó mà hãy diễn đạt lại rằng bạn đang báo cáo vượt cấp một vấn đề hoặc cần thêm thông tin, để không bị xem là hành xử theo cảm xúc. Hãy nhận vai người ghi chép trong cuộc họp: việc này thể hiện sự khiêm tốn, giúp bạn định hướng cuộc thảo luận, tạo khoảng lặng để giữ bình tĩnh và cho mọi người thấy ý kiến của họ được ghi nhận. Tránh phản bác bằng những giả định cực đoan kiểu &amp;ldquo;nếu cho mọi người tự chọn thì sẽ loạn&amp;rdquo;, vì cách nói này ngầm cho rằng người đề xuất thiếu suy xét và làm tốn thời gian.&lt;/p&gt;
&lt;p&gt;Đừng ngắt lời chỉ để sửa chi tiết không quan trọng; nếu cần, hãy trao đổi riêng sau. Chọn thời điểm phù hợp cho các cuộc họp quan trọng, tránh thứ Hai, thứ Sáu, giờ ăn trưa và cuối ngày, đồng thời giữ lịch họp 1:1 cố định hằng tuần. Cuối cùng, hãy sắp xếp chương trình họp theo mức độ ưu tiên: thảo luận kỹ hai vấn đề tốt hơn lướt qua năm vấn đề mà không đi đến kết luận.&lt;/p&gt;
&lt;h2 id="code-is-the-new-no-code"&gt;&lt;a class="link" href="https://lumberjack.so/code-is-the-new-no-code/" target="_blank" rel="noopener"
&gt;Code is the new no-code&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;David Szabo-Stuban và Evan Boyle (CEO của GenSX) cho rằng lời hứa của phong trào no-code đang được hiện thực hóa theo một cách bất ngờ: bằng chính mã nguồn. Các công cụ lập trình trực quan dễ dùng lúc đầu, nhưng độ phức tạp tăng rất nhanh; một luồng tự động hóa của đội marketing trên n8n có thể phình to thành 47 nút nối chằng chịt như mạng nhện. Lớp trừu tượng cũng không che giấu được hết, người dùng vẫn phải học các khái niệm kỹ thuật, và những người dùng thành thạo cuối cùng thường chuyển sang viết mã.&lt;/p&gt;
&lt;p&gt;Theo các tác giả, trợ lý lập trình AI như Claude, ChatGPT hay GitHub Copilot đã thay đổi cục diện: người dùng mô tả mục tiêu bằng lời, AI sinh ra mã chạy được và giải thích từng phần, nhờ đó việc học diễn ra dần dần thay vì liên tục &amp;ldquo;đụng tường&amp;rdquo;. Kết hợp với mô hình thành phần (component) quen thuộc như React, mã nguồn trở nên trực quan hơn cả trình soạn thảo dạng nút. Bài viết minh họa bằng GenSX, nơi một luồng lấy dữ liệu CRM, lọc và lập báo cáo được viết thành các thành phần JavaScript dễ đọc, đồng thời lập luận rằng phần lớn quy trình mang tính tuần tự nên cấu trúc cây của mã dễ hiểu hơn cấu trúc đồ thị.&lt;/p&gt;
&lt;h2 id="how-to-improve-jvm-based-application-startup-time"&gt;&lt;a class="link" href="https://softwaremill.com/how-to-improve-jvm-based-application-startup-time/" target="_blank" rel="noopener"
&gt;How to Improve JVM-Based Application Startup Time?&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Michał Zyga (SoftwareMill) so sánh năm cách rút ngắn thời gian khởi động ứng dụng JVM, điều quan trọng với serverless và microservices. JVM khởi động chậm vì phải nạp, xác minh và khởi tạo rất nhiều lớp. Class Data Sharing (CDS) lưu sẵn các lớp lõi của JDK và được bật mặc định từ JDK 12; Application Class Data Sharing (AppCDS) mở rộng cơ chế này cho cả các lớp của ứng dụng và dễ dùng hơn từ JDK 19. GraalVM biên dịch trước (AOT) thành tệp thực thi gốc, CRaC chụp lại trạng thái tiến trình JVM bằng CRIU (chỉ chạy trên Linux) để khôi phục khi cần, còn Project Leyden là hướng cải tiến mới của JDK, lưu thêm dữ liệu tối ưu hóa.&lt;/p&gt;
&lt;p&gt;Kết quả đo trên hai máy (Intel i5 cá nhân và Xeon trên Google Cloud, mỗi cấu hình chạy 50 lần) cho thấy AppCDS giúp khởi động nhanh hơn gấp đôi so với mặc định, CRaC và GraalVM nhanh nhất, còn Project Leyden nằm ở giữa và vẫn đang phát triển. Tác giả khuyên chọn theo ngữ cảnh: AppCDS dễ áp dụng với lợi ích vừa phải, CRaC hợp với dịch vụ chạy lâu vì vẫn tận dụng được tối ưu JIT lúc chạy, còn GraalVM phù hợp với ứng dụng ngắn hạn cần khởi động cực nhanh.&lt;/p&gt;
&lt;h2 id="domain-driven-design"&gt;&lt;a class="link" href="https://dev.to/lovestaco/domain-driven-design-3i2j" target="_blank" rel="noopener"
&gt;Domain Driven Design&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Athreya (Maneshwar) giới thiệu Domain Driven Design (DDD), phương pháp thiết kế phần mềm lấy lĩnh vực nghiệp vụ (domain) làm trung tâm thay vì chỉ tập trung vào kỹ thuật. Bài viết giải thích các khái niệm cốt lõi: domain và subdomain; Bounded Context vạch ranh giới rõ ràng để mỗi mô hình độc lập; Entity có danh tính riêng còn Value Object bất biến và được xác định bằng thuộc tính; Aggregate gom nhóm các đối tượng liên quan dưới sự kiểm soát của Aggregate Root; Domain Event giúp các phần của hệ thống ít phụ thuộc vào nhau; Repository, Service và Factory lo việc lưu trữ, xử lý và khởi tạo đối tượng; cuối cùng là Ubiquitous Language, ngôn ngữ chung giữa lập trình viên và chuyên gia nghiệp vụ.&lt;/p&gt;
&lt;p&gt;Các khái niệm được minh họa qua một nền tảng thương mại điện tử, trong đó quản lý đơn hàng tách biệt khỏi danh mục sản phẩm, kèm ví dụ TypeScript về lớp Order quản lý trạng thái và OrderRepository đảm nhận lưu trữ. Tác giả lưu ý DDD phù hợp với các dự án phức tạp, lâu dài cần sự phối hợp chặt chẽ giữa đội phát triển và phía nghiệp vụ, nhưng dễ dẫn đến thiết kế quá mức với ứng dụng CRUD đơn giản; muốn áp dụng tốt, bạn cần vững các mẫu thiết kế và nguyên lý hướng đối tượng.&lt;/p&gt;
&lt;h2 id="bonus-vài-ảnh-hay-ho-đến-từ-bytebytego"&gt;Bonus: Vài ảnh hay ho đến từ &lt;a class="link" href="https://bytebytego.com/" target="_blank" rel="noopener"
&gt;ByteByteGo&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/66d12ddc-2abe-4a98-82d5-ee177e80487c_1470x1600.png"
loading="lazy"
alt="Monolith vs Microservices vs Modular Monoliths"
&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>