Git Is Simpler Than You Think

By Nick Farina

It was about one year ago that we switched to Git. Previously, we used Subversion, through the Mac app Versions, which (rightly) holds an Apple Design Award.

I made the executive decision to leave our comfy world of Versions because it seemed clear that Git was winning the Internet. There was much grumbling from my teammates, who were busy enough doing actual work thank you very much.

But I pressed forward. We signed up for accounts on Github. We learned how to type 'git push' and 'git pull'. We became more confident. Git is just like any other source control system! But it wasn’t long before one of our devs called me over to look at a…situation.

It might as well have printed PC LOAD LETTER. “Falling back to patching base and 3-way merge?” That does not sound good at all. Or maybe it’s completely normal? I type 'git status'.

“Not currently on any branch?!” Now I’ve done it. We’re going to lose all the work he did today. Sweat is beading up on my forehead. Everyone is watching me to see if I can figure this out. After all, I got us into this mess.

Maintenance Required

Git is not a Prius. Git is a Model T. Its plumbing and wiring sticks out all over the place. You have to be a mechanic to operate it successfully or you’ll be stuck on the side of the road when it breaks down. And it willbreak down.

By now we all know how to drive Git. We learned it by typing “git tutorial” into Google. We studied guides, how-tos, cheat sheets.

Did you know the top result for “git tutorial” is this manpage on I will give you a gold star if you can read the whole thing without falling asleep.

So instead let’s pull over, open the hood up, and poke around.

The Basics

We’ll run through some basic commands to make a repository for our examples:

~$ mkdir mysite
~$ cd mysite
~/mysite$ echo "<title>All About Cats</title>" > index.html
~/mysite$ git init
~/mysite$ git add index.html
~/mysite$ git commit -m "First commit, added a title."

Now we have a git repository with one file and one commit, that is to say, one “version”. Let’s make a change and commit a second “version”:

~/mysite$ echo "<center>Cats are cute.</center>" >> index.html
~/mysite$ git commit -a -m "Added some text."
~/mysite$ open index.html 

With me so far? Good.

The Repository

In Git there is no “client” and “server”. A repository is a repository, no matter if it’s on my machine, your machine, or

Each repository lives in a single hidden folder called .git. This is in stark contrast to Subversion which infects your source tree with little.svn folders everywhere.

The .git “repository” is more than just metadata and bookkeeping. It’severything. All of your source, all your changes, all your branches, all your commit notes with swear words and in-jokes.

Go ahead, delete your index.html. As long as your .git folder is intact, you can reconstruct it:

~/mysite$ rm index.html
~/mysite$ git checkout -- .
~/mysite$ ls

That would work even if you’d deleted a bunch of subfolders and huge files and whatever. Poof, it’s all back.

This explains why, when you “checkout” (clone) the Ruby on Railsrepository from Github, it takes a surprisingly long time. You’re downloading onto your machine, into your new rails/.git folder, the entire history of Ruby on Rails. Every tiny change from David’s initial commit in 2004, it’s all sitting there on your disk.

This troubled me greatly at first. It’s so inefficient! My precious disk space!

And I can only say that disk space turned out to be a non-issue. But it took me some time. Maybe go take a walk outside, look at some trees, and come back later when you’ve accepted it.

User Interface

Now if you’re a curious person, you’ll likely say “Wait. Go back. Where did you get the line ’git checkout -- .’ from? What does that evenmean?”

To which I’ll respond, “I don’t know. I Googled it.”

And this brings us to Git’s greatest shortcoming, which is that Git’s terminology and syntax is fracking inscrutable.

Git’s overloaded, confusing language is absolutely the only part of it that sucks. They meant well. They chose words that sound familiar, likebranch, checkout, tag, merge. But they often mean different things. Then you get the feeling that, as features were added and rethought, they just picked new unused words as they went along. Stage, fetch, rebase,remotes.

And because of Git’s explosive popularity, it’s a total Emperor-Has-No-Clothes situation. If you’re anything like me, you probably wondered why you were the only stupid person on the planet who didn’t intuitively get Git already. Even the beloved Github, though unaffiliated with Git, is much the same: as overwhelming as it is awesome.

Ultimately, when you look at Git, you don’t see a product that was “designed” holistically. It’s more like a collection of command-line utilities.

A Collection of Command-Line Utilities

This is a much better way to think about Git, and in fact this is what Git originally was. Git started life as a week-long project of Linus Torvalds to replace the old version control system they were using at the time to manage contributions to the Linux kernel.

You can’t design and build a fully-featured distributed version control system in a week. But you can design your data model. And it had better be really, really simple.

So what’s Git’s data model? To answer that, we need to dig into that mysterious .git folder.

The So-Called “Object Database”

In mysite/.git, there is a subfolder called objects. It should contain these folders and files (edited for clarity):

~/mysite $ find .

These files with mangled-looking names are the “objects” in our database for mysite. An object can be either a commit, a tree, a blob, or atag. They’re compressed with zlib, but you can extract and examine them easily.

If we were to extract the object 23/5810…, we would see:

<title>All About Cats</title>

…which is the old version of index.html! So that’s a blob, that is, a particular version of one file. If we extract the object 0d/0321…, we get:

commit 227tree 5b853962ae2f41f608428968f8fffbf72f6cec2b
parent b1a701e38645a3e60bc17a786cdd9062a15b5a21
author Nick Farina <> 1315106589 -0700
committer Nick Farina <> 1315106589 -0700

Added some text.

…which is a commit object (our last commit).

If you’re following along, you’ll notice that you don’t have an object0d/0321. Your commit will have a different mangled name because your author name and email won’t match mine. You see, the “mangled names” of these files are SHA1 Hashes of their contents. If we computed the hash of the blob <title>All About Cats</title>, we’d get:


Recognize that hash from the 23/5810… filename above? Git chops off the first 2 characters of the hash and uses that as a directory name, so we don’t end up with too many of these little files in one place.

Git calls this “content-addressable” to sound fancy, but really it’s just a naming scheme. See, these “objects” have to be called something, so they might as well be named according to their contents.


Now if you’re reasonably paranoid, you may ask: “What if two different objects compute the same SHA1 hash code? Won’t this happen someday?”

It turns out you’ll never generate two of the same SHA1 hashes. The chances are miniscule. There’s room for all kinds of flowery comparisons like: You’d have to generate more hash codes than the number of stars in the universe before you’d get two of the same!

But my favorite is from Pro Git: “A higher probability exists that every member of your programming team will be attacked and killed by wolves in unrelated incidents on the same night.”


A commit represents a complete version of your code. Look again at the object file representing our last commit:

commit 227tree 5b853962ae2f41f608428968f8fffbf72f6cec2b
parent b1a701e38645a3e60bc17a786cdd9062a15b5a21
author Nick Farina <> 1315106589 -0700
committer Nick Farina <> 1315106589 -0700

Added some text.

This chunk of text contains enough hints to reconstruct the entire contents and history of our repository as it existed in this version.

The hash 5b8539… is the object containing the state of our tree. A tree object is basically a manifest of files and folders (simplified here):

blob 2d48a74575acab21d702f17f4ecce126b7e34ab0  index.html
blob b8ca7d5cba87d5123182375871234a76d6f78ff2  someotherfile.html  <- example 2nd blob
tree 3182375871234a76d6f78ff2b8ca7d5cba87d512  Documentation       <- example subfolder

This represents the filesystem structure at this point in time. Cleverly, subfolders are represented by pointers to other tree objects. Recursion! The “blob objects” then contain the actual file data like <title>All About Cats</title>.

To get the previous version of our repository, look at the “parent” hash beginning with b1a701 (again, different for you). This is the object containing the previous commit.

So just by starting with our last commit object, we’ve explored the entire contents of our repository.


If we had a thousand objects in our database, it would be pretty hard to guess the hash of our last commit. So we’d better write it down somewhere.

~/mysite$ cat .git/refs/heads/master

This is what a branch is: it’s simply the hash of the last commit scribbled down in a file. It’s a clue, a starting point, sometimes called atip because this represents the tip of the iceberg that is the entire history of the master branch.

And since you can have multiple branches in a repository, we should also remember which one we’re working on right now.

~/mysite$ cat .git/HEAD
ref: refs/heads/master

It’s forehead-slapping simple. Whenever you execute a Git command, it first looks at .git/HEAD to see what our working copy is supposed to be. And that contains a reference to either a branch name or a commit object (that case is a detached HEAD). If it’s a branch name, look at the branch file to see what commit object it is. Then open up the commit object to find all the trees and blobs and parents and it’s turtles all the way down.


One last thing to ponder. Our objects folder contains 6 files. Three for the first version’s commit object, tree, and blob. And three again for the last version’s commit object, tree, and blob.

If you zipped up your entire mysite folder right now and emailed it to me, I could unzip it and make another change to index.html and commit that change to my local copy on disk. Let’s say I changed the line to say<center>Cats are TERRIBLY cute.</center>.

Now I have 9 files in my objects folder. Three more for the commit I just made, its tree and blob.

I want to share my changes with you. So I zip up the 3 object files you don’t have and email them to you.

Are you ready for this? You take my three object files and just dump them into your objects folder. You don’t have to worry at all about overwriting anything, about losing data, about screwing up your repository, because we’ve already established that these file names arecompletely unique. Wolves in the night, remember?

You’ve just manually performed a git fetch, which is the safest operation ever because it’s just collecting someone else’s unique commit files and tossing them into to your database.

In my email, I’ll say “My latest commit is 3bd54c.” So you type “git checkout 3bd54c” and boom you’re looking at my latest changes.

If we emailed back and forth a lot, I might want to add you as a remoteso that Git does the moving of files around for me. And I might scribble down the latest commit hash that I got from you in a file calledorigin/master or something. Sound familiar?


Octobi Wan Catnobi by

For me, understanding the structure of the object database was my Eureka moment for Git. After that, I could start to understand not just how Git worked, but why.

The best way to get yourself out of a Git disaster scenario is to understand what Git is trying to do for you.

And when you understand how Git works, your Google Power will increase tenfold. How did I know to type “git checkout -- .”? Well I just looked online until I found a command that sounded like it did what I would do myself if I had to write some code to poke around the object database.

There’s a lot more to grok about Git from here. Merging, rebasing, and staging come to mind. But it’s not so hard now; it’s all just a bunch of fancy shell scripts anyway.

Những nguyên tắc, những định luật của lập trình mà chúng ta nên có sẵn trong đầu

Nguồn :

Người dịch : Phan Hoàng Minh (


Nguyên tắc Demeter

Còn có tên gọi khác là nguyên tắc “càng biết ít càng tốt”.

Demeter là tên gọi của Nữ thần nông nghiệp, cũng là nữ thần phân phát trong thần thoại Hi Lạp. Tên bà được dùng để đánh dấu sự ra đời của nguyên tắc này, đây có thể xem là một triết lý nền tảng của việc lập trình được sinh ra từ một aspect-oriented programming (AOP) project cùng tên.

Quan điểm cơ bản của nguyên tắc này chính là : tối giản sự hiểu biết của 1 object về cấu trúc, thuộc tính của các object khác ngoài nó (bao gồm các thành phần con).

Nói một cách đơn giản là không được tiếp xúc với thuộc tính, method của các object khác một cách trực tiếp.

#Vi phạm nguyên tắc Demeter

#Không vi phạm nguyên tắc Demeter

Định luật Wirth

“Software gets slower faster than hardware gets faster” – “Tốc độ tiến hóa của phần cứng không bằng tốc độ thoái hóa của phần mềm.”’s_law

Có lẽ ý chính của nó là : lập trình ngày càng dùng nhiều tài nguyên phong phú nên framework phải luôn tiến hóa để phục vụ cho việc đó. Suy ra, tốc độ phần cứng dù có tang lên đi nữa thì tốc độ phần mềm cũng chẳng hề thay đổi gì.

Định luật Brook

Đây là một định luật dựa trên kinh nghiệm thực tế : “Đưa thêm người vào 1 project đang chậm, sẽ chỉ khiến nó càng chậm hơn.”

Hay có thể nói theo một cách khác nữa là “Tập hợp 9 bà bầu lại cũng không thể khiến đứa trẻ ra đời sau 1 tháng.”

Luận thuyết cơ bản của định luật này là

  • Cần thời gian để quen với project
  • Công sức dành cho việc communication sẽ tăng

Định luật Conway

“Organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations.”

“Một công ty thiết kế hệ thống thế nào cũng sẽ làm ra những thiết kế giống y hệt với thiết kế hệ thống của chính công ty họ.”

Nghiên cứu gần đây chỉ ra rằng hệ thống của công ty là nhân tố ảnh hưởng lớn nhất đến vấn đề phát sinh ra bug của sản phẩm.

Nguyên tắc bất ngờ nhỏ nhất (least astonishment)

Trong trường hợp trên cùng 1 interface có 2 yếu tố hành xử mâu thuẫn với nhau, hoặc cách hành xử không rõ ràng thì cần phải chọn cách hành xử nào gây bất ngờ ít nhất cho người sử dụng.

Đây là 1 nguyên tắc về giao diện người dùng.

Một ví dụ đơn giản :

Trên 1 interface có 2 chức năng :

  • Ấn ctrl+Q để thoát chương trình.
  • Nhập macro (lưu 1 tổ hợp phím mang 1 chức năng nào đó để tiện cho việc sử dụng về sau).

Sẽ có trường hợp user muốn dùng Ctrl+Q cho macro của mình, nên hành xử đúng với nguyên tắc bất ngờ nhỏ nhất chính là : trong khi nhập macro thì ctrl+Q được coi như là tổ hợp phím bình thường, không phải là lệnh tắt chương trình. Đây chính là điều gây bất ngờ ít nhất cho người dùng.

Nguyên tắc Boy Scout

Nguyên tắc của các tổ chức Boy scout chính là : lúc đi phải sạch đẹp hơn lúc đến.

Trong lĩnh vực lập trình thì nguyên tắc đó sẽ được hiểu là “Khi bạn checkin 1 module thì lúc đó nó phải đẹp hơn lúc bạn checkout.”

Nguyên tắc YAGNI

Viết tắt của “You ain’t gonna need it” – Cái (chức năng, phần) ấy rồi sẽ không cần thiết.

Đó là một câu khẩu ngữ nhắc nhở người lập trình rằng trong quy trình eXtreme Programming (lập trình cực hạn) thì : “Chưa phải lúc cần thiết thì chưa được phép làm.”

Nguyên tắc DRY

Viết tắt của “Don’t repeat yourself” – với ý nghĩa là “Đừng lặp lại những gì giống nhau”.

Khi nguyên tắc này được áp dụng tốt, dù ta có thay đổi 1 phần thì những phần không liên quan cũng sẽ không bị thay đổi theo. Hơn nữa, những phần có liên quan sẽ được thay đổi cùng 1 lượt, giúp ích rất nhiều cho cả khâu estimate và khâu thực hiện.

Nguyên tắc KISS

Viết tắt của “Keep it simple, stupid” – “Cứ đơn giản thôi, đồ ngu!”. Đây là 1 triết lí của Hải quân Mỹ.

Những triết lý tương tự có thể kể đến là :

Phương châm dao cạo Okham (Okham’s razor) – “Không đưa ra nhiều giả thiết nếu không cần thiết. Cái gì cần ít giả thiết để chứng minh sẽ không thể chứng minh được bằng nhiều giả thiết.”

Albert Einstein – “Làm cái gì cũng nên đơn giản nhất có thể, nhưng đơn giản quá thì không được”.

Leonardo da Vinci – “Đơn giản nhất chính là tinh xảo nhất”.

Antoine de Saint- Exupéry – “Hoàn hảo, không phải là không thêm vào được nữa, mà là không thể bớt đi được nữa”.

Nguyên tắc SOLID

Tập hợp những nguyên tắc trong lập trình hướng đối tượng. Các chữ cái đầu hợp lại thành SOLID.

SRP (Single Responsibility Principle) – “Một class chỉ được có 1 nhiệm vụ” hay nói cách khác, “nếu muốn chỉnh sửa class thì chỉ được phép có 1 và chỉ 1 lý do”.

OCP (Open/closed principle) – “Mở class khi cần mở rộng nó, đóng class khi cần chỉnh sửa nó”.

LSP (Liskov substitution principle) – “Subtype phải luôn có thể được thay thế bằng supertype”.

ISP (Interface segregation principle) – “Việc dùng nhiều interface cho các client khác nhau, tốt hơn là việc chỉ dùng 1 interface cho cùng lúc nhiều mục đích” hay nói cách khác “Không được phép hạn chế access vào những method mà client không sử dụng”.

DIP (Dependency inversion principle) – “Module tầng trên không được phụ thuộc vào module tầng dưới. Bất cứ module nào cũng phải phụ thuộc vào cái trừu tượng, không phải vào cái cụ thể”.



By Thanh

I. Khái lược về Scrum


Scrum cơ bản là bộ khung làm việc (framework) hay có thể hiểu nôm na là cách thức làm việc để trở nên “linh hoạt” trong phát triển phần mềm.

Scrum là khung làm việc được sử dụng để quản lý quá trình phát triển các sản phẩm phức tạp. Scrum không phải là một quy trình hay một kĩ thuật cụ thể để xây dựng sản phẩm; hơn thế, nó là một khung làm việc cho phép ta sử dụng nhiều quy trình và kĩ thuật khác nhau. Scrum làm rõ hiệu quả của công tác quản lý và phát triển sản phẩm, từ đó cho phép ta cải tiến nó.

2.Scrum có các tính chất:

  • Scrum (hay agile nói chung) được xếp vào nhóm “Feature-driven development“. Sản phầm được phát triển theo tính năng, chứ không phát triển sản phẩm theo kiến trúc hệ thống.
  • Scrum khác với các mô hình Agile khác ở chỗ nó là mô hình hướng khách hàng (Customer oriented), vai trò của khách hàng trong việc đánh giá sản phẩm rất quan trọng. Chỉ sau mỗi sprint (2-4 tuần) khách hàng sẽ thấy được sự thay đổi của sản phẩm của mình qua đó đưa ra phản hồi sớm để định hướng.
  • Scrum giảm thiểu tài nguyên dành cho việc quản lý mà tập trung nhiều hơn cho những công việc liên quan trực tiếp đến việc làm ra sản phẩm. Bằng cách giảm vai trò quản lý (PM) bằng cách đẩy việc quản lý tới từng người
  • Giảm thời gian dành cho việc viết tài liệu bằng cách tăng thời gian trao đổi trực tiếp. Thông thường khi estimate công việc, thì team estimate cả thời gian dành cho communication để hoàn thành task đó nữa.

Khung làm việc Scrum bao gồm một Nhóm Scrum với các vai trò được phân định rõ ràng, các sự kiện và các quy tắc. Mỗi thành phần trong khung làm việc phục vụ một mục đích rõ ràng và là nòng cốt trong việc sử dụng cũng như thành công của Scrum.


3.Vai trò trong Scrum

Trong Scrum có 3 vai trò: Chủ sản phẩm (Product Owner), Nhóm phát triển, và Scrum Master. Trong Scrum sẽ không có vai trò Quản lý dự án (Project manager) hay Trưởng nhóm kỹ thuật (Technical lead)

  • Product Owner: Là người chịu trách nhiệm cao nhất đối với sản phẩm và nhóm phát triển. Chủ sản phẩm có trách nhiệm làm việc với chủ đầu tư để hiểu yêu cầu về sản phẩm, quản lý những yêu cầu đó, tạo ra những “câu chuyện người dùng” đối với sản phẩm và truyền đạt những thông tin đó đến đội phát triển. Cơ bản là nếu nhóm gặp những vấn đề hay thắc mắc gì liên quan đến sản phẩm, hãy tìm gặp Product Owner.
  • Nhóm phát triển: Là một tập hợp những kỹ sư “liên chức năng”- nghĩa là công việc của họ không cố định ở lập trình, kiểm thử, phân tích hay thiết kế. Tùy theo yêu cầu công việc mà họ sẽ đảm nhận những vai trò tương ứng. Nhóm phát triển được quyền chủ động tổ chức công việc, ước lượng khối lượng công việc và cam kết hoàn thành công việc đã cam kết. Trong Sprint, nhóm phát triển có tiếng nói lớn nhất và những bộ phận khác có nhiệm vụ hỗ trợ những điều kiện tốt nhất để nhóm làm việc hiệu quả
  • Scrum Master: Nhiệm vụ của Scrum Master là giúp mọi người trong nhóm hiểu được Scrum, làm theo Scrum đồng thời hỗ trợ nhóm phát triển để họ có thể toàn tâm toàn ý làm việc. Vừa giống ông chủ vừa giống osin, kiểu vậy. Nếu có ai đó thắc mắc về quy trình trong Scrum, ý nghĩa của Scrum hay những vấn đề liên quan đến Scrum khác, hãy tìm gặp Scrum Master.Image

II. Scrumban là gì?

Scrum là giải pháp tốt nhất cho product và phát triển project. Kanban là giải pháp tốt nhất để hỗ trợ sản xuất. Scrumban là sự kết hợp của Scrum, Kanban và bao gồm toàn bộ những ưu điểm của cả 2 phương thức trên. Nó khuyến khích các đội phải liên tục cải tiến quy trình cùng với phương thức Kanban.

Scrumban được giới thiệu như một quy trình đơn giản để quản lý những project phức tạp. Hiện nay Scrumban được áp dụng tốt nhất khi phát triển trên web, software development hoặc maintenance.


  • Chia công việc thành những list nhỏ, phân tách nhỏ để bàn giao. Sắp xếp danh sách này theo thứ tự ưu tiên và ước lượng tương đối thời gian, công sức bỏ ra cho mỗi item.
  • Chia thời gian thành những khoảng thời gian ngắn, lặp lại thường là từ 1-4 tuần, với khả năng có thể bàn giao code sau mỗi một chu trình.
  • Dựa trên những hiểu biết đã đạt được bằng cách kiểm tra các phiên bản sau mỗi lần lặp, tối ưu hóa các kế hoạch bàn giao và bản cập nhật ưu tiên trong hợp tác với các khách hàng.
  • Đánh giá quy trình bằng cách nhìn lại những gì đã làm sau mỗi chu trình.


Quy trình làm việc

  • Chia công việc thành những phần nhỏ, viết mỗi phần vào một miếng giấy note và dán lên tường
  • Sử dụng tên cột để minh họa vị trí của mỗi item trong quy trình làm việc
  • Giới hạn công việc trong sự phát triển(WIP): Phân công rõ ràng giới hạn cho bao nhiêu item có thể được thực hiện ở mỗi workflow.
  • Ước lượng thời gian quản lý (thời gian trung bình để hoàn thành một item, đôi khi gọi là “cycle time”) và đánh giá quy trình để lập thời gian quản lý sao cho nhỏ nhất và có thể dự đoán.

3.Quy trình làm việc

Kết quả trực tiếp của sự khác biệt này trong các quy tắc là cách mà các work item được xử lý theo thời gian

Trong Scrum, bạn lựa chọn những việc mà bạn sẽ sẵn sàng làm cho sprint sau.

Làm lần lượt theo thứ tự, làm tất cả mọi việc mỗi sprint trong một vài tuần (khoảng thời gian thông thường cho sprint) và chuyển chúng sang trạng thái hoàn thành (cột Done) thì cuối cùng sẽ xử lý hết những sprint còn ở trạng thái chờ


Ở Kanban, bị giới hạn bởi kích thước của hàng đợi, gọi là giới hạn WIP. Điều này có nghĩa là bạn có thế thay đổi items ở hàng đợi bất cứ lúc nào, và không có kết thúc sprint


4.Scrumban = Scrum + Kanban

Sử dụng quy tắc tự nhiên của Scrum là Agile

Sử dụng quy trình phát triển của Kanban để team có thể tiếp tục cải tiến quy trình

Trong Scrumban, chúng ta có thể lập những kế hoạch lặp lại trong những khoảng thời gian đều đặn, đồng bộ với việc đánh giá và có thể xem lại những gì đã làm. Điều này làm giảm đáng kể chi phí.


Lợi ích

  • Chất lượng
  • Đúng thời gian
  • Thời gian quản lý ngắn
  • Tiếp tục cải tiến
  • Ít rủi ro, giảm lãng phí
  • Có thể thêm chức năng vào Scrum khi cần

Khi nào nên sử dụng Scrumban

  • Dự án bảo trì
  • Dự án mà thường xuyên có lỗi không mong đợi

Scrum – First thought

Ở những nơi không sử dụng Scrum hoặc thất bại trong việc áp dụng Scrum thì có hai điều cốt lõi sau:

– Thứ nhất, môi trường out source nên không tự chủ được trong sự linh động về việc phải “tung” sản phẩn của mình ra khi nào.

– Thứ hai, nếu là làm product thì tính cạnh tranh cũng không cao giữa các đối thủ, với tâm lý, nó làm rồi thì mình tìm cái khác để làm, cũng ít làm mô hình cổ phần doanh nghiệp, nên cũng chẳng vấp phải sự hối thúc từ HĐQT, nên cứ làm xong rồi demo luôn, rồi release luôn.



Scrum Framework, ảnh: Bas Vodde et al.

– Và thêm vài cái phụ nho nhỏ đó là thiếu tầm nhìn chiến lược từ phía khách hàng + nhà phát triển và lối mòn trong tư duy phát triển phần mềm theo kiểu hướng kiến trúc hệ thống, không rõ ràng sẽ không dám làm. Chính các điều này đã làm cho sức hút, sức mạnh về sự linh động của Scrum không được trân trọng.

Ngược lại với đó là các nước đang áp dụng rất thành công Scrum, đó là các nước Âu Mỹ, nơi mà Scrum – một framework (khung làm việc) chứ không phải là methodology (phương pháp luận) cho phép ta sử dụng nhiều quy trình và kĩ thuật khác nhau, vai trò của khách hàng trong việc đánh giá sản phẩm rất quan trọng. Chỉ sau mỗi sprint (2-4 tuần) khách hàng sẽ thấy được sự thay đổi của sản phẩm của mình qua đó đưa ra phản hồi sớm để định hướng, sự canh tranh cũng được nâng lên, bạn không cần có một phiên bản phần mềm hoàn hảo, nhưng chỉ cần đủ để nó tiếp cận và định hướng được thị trường đầu tiên.

Khi trực tiếp tham gia (hoặc chứng kiến) các nhóm làm việc dựa trên Scrum, bạn sẽ thấy được sự thay đổi, xoay vòng với tốc độ chóng mặt.

Đó là những cảm nhận đầu tiên về Scrum (hay Agile nói chung) đi từ hướng tiếp cận tại sao họ áp dụng Scrum thành công, còn mình thì không, chứ không phải từ suy nghĩ là làm thế nào để áp dụng nó. :)

What does TDD mean?


Pawel Olesiejuk


Test Driven Development (TDD) is not about writing tests. Writing tests is writing tests, period. TDD is more than that, it’s a methodology.  It has started as a part of the agile methodology invented by Ken Beck called eXtreme Programming (we recommend Kent Beck’s book “Extreme Programming Explained”). The main idea of TDD is to write tests before code. It’s seems to be irrational but it’s not!

I try to do TDD every time when I’m writing code, but I won’t name myself a TDD expert. Experts like Robert C. Martin a.k.a. Uncle Bob, Kent Beck, Roy Osherove, Corey Haines and my teacher Kristoph Manuszewski, just to name a few, inspired me.

I’d like to share my knowledge about TDD and I’ll refer to articles/posts/books/screencast of people mentioned above.

It’s so f… simple

Most programmers can’t understand ‘Why the hell should I write a test for all code that I’m writing? It is so f… simple‘. Maybe it is, maybe it isn’t, but you can’t be sure that in the future the code remains the same. Edward V Berard says that ‘Walking on water and developing software from a specification are easy, if both are frozen’. Requirements are changing all the time, the environment is no longer stable. Perhaps someone else will extend/change your code. He is not you and he doesn’t know all the tricks you’ve used in your code. He can easily break your code without knowing it. This “he” could even be you after a couple of months.

Benefits of using TDD

It is proven that using TDD reduces the amount of bugs by at least 50% (The Cost of a Bug). I mean good TDD, not only automated tests. Consider this, how long does finding a bug take (and what about when an end-user finds it)? How long does tracing and fixing the bug take? How long do you need for integration tests to confirm you haven’t broken anything after fixing a bug?

Let’s assume the above will take 15 minutes to 3 hours per bug. How many bugs can there be in a single project? 100? 1000? So how much time do you spend on fixing them? This can easily grow up to 1,5h * 1000 = 1500h. Are you still there?

What would you say if you can save 750h in your project when using TDD? I think it is worth trying.

Tests are your safety net

Good tests (later on I’ll use “tests” for “good tests”) assure you that you haven’t broken anything in your previous functionality. This is the first (but not the only one) reason why you must (SIC!) write a test for every production code (production code is everything but tests) based functionality. If you have a code coverage of over 90% you will have certainty your code works. You won’t have to run the application to know that. This is your ‘safety net’, your parachute. Your tests should be as trustworthy as a net or a parachute.

Test driven code shows the user standpoint

When you write a test before writing production code you’ll understand how you (or somebody else) will use it, because the test is the first user of your code. And when you think from a user’s standpoint you will think about the interface first. This is a good design practice. Your code will be easy to use. It will become self explanatory.

Test Driven Design forces you to think upfront

Often after creating some class, you want to use it in another place and then you realize it cannot be reused in an easy way. It’s great and does lots of beautiful things at once. But it isn’t sufficiently useful. It isn’t flexible enough. It isn’t configurable, because you didn’t think of such things before.

If you’d written tests before you’d know about this stuff earlier and wrote this class in a different way. This is the greatest benefit of TDD!

Really, try it!

Usage specification better than documentation

Another advantage of tests is when someone reads them he’ll know how to use your code. Tests are like specification. Even better, they are usage specification, a tutorial ‘how to use the code’. Imagine that you are starting to use a new tool. With the tool you’ve got fat documentation with code samples on the back. What do you read first, API documentation or code samples? Furthermore, tests and code will always be in sync, so you don’t have to bother with synchronizing your documentation while the code is changing.

S.O.L.I.D. principles become natural

The next thing about writing tests before production code is that you won’t create big complex classes, because you really don’t want to write a complex test with lots of stubs. So, you will create small classes with only one responsibility. Your code will be decoupled, flexible and configurable. You don’t have to worry about S.O.L.I.D. principles. It will be so natural to follow them.

The proof of the pudding ….

In the end the proof of the pudding is in the eating. Therefor, to convince you probably the best example is a ‘real’ example. Robert C. Martin wrote series of articles about a young person (after school) who wants to become a programmer. But he didn’t want to write tests because he ‘can do this right without tests. It is so f… simple‘. I really recommend reading the whole story! You will find it here: -> By Topic -> Craftsman

Test Driven Development gives you the opportunity to create well designed, flexible and easy to use code, good dependency decoupling and specification at once. Saying that writing tests before code costs you too much time is senseless. Redesigning, rewriting, debugging and creating specifications takes much more time. Furthermore, tests can assure you that your code (always) works, this is a priceless thing and nothing but automatic tests can give you such certainty. So… DO TDD!!

Silicon Valley – Season 1

Thung lũng Silicon (Phần 2) - Silicon Valley (Season 2)

Phim Thung Lũng Silicon lấy bối cảnh trong cơn sốt công nghệ cao, hiện đại tại Thung lũng Silicon, những anh chàng sinh viên xử lý kém nhưng với lòng quyết tâm, nhiệt huyết và hài hước lại trở thành những người thành công….

Xoay quanh Richard, 1 lập trình viên máy tính. Anh phải lựa chọn giữa việc bán hẳn dự án thuật toán siêu nén của mình cho Gavin Belson lấy 10 triệu đô hoặc chỉ nhận 200 nghìn đô tiền tài trợ của Peter Gregory nhưng được toàn quyền sở hữu nó và cùng bạn bè mình phát triển nó để thay đổi cả thế giới.

Phần 1 tập trung vào việc Richard quyết định lập công ty riêng với tên Piped Piper. Piped Piper cũng là tên của ứng dụng mà Richard và các đồng nghiệp đang phát triển. Phim này bạn nào là dân IT nhất là những người có ý định khởi nghiệp thì sẽ thấy rất hay và học hỏi được nhiều kinh nghiệm quý giá. Từ việc tìm kiếm tên công ty, thuyết phục chủ đầu tư, sự khốc liệt trong thương trường khi những tài sản trí tuệ bị đánh cắp ngay trước mặt chúng ta. Với phương châm nhanh chân thì sống, chậm chân thì chết, cùng xem Scrum đã cứu cả đội như thế nào. Qua đó cũng cho thấy được những bộ óc thiên tài cùng với niềm đam mê vô tận, bạn bè đồng tâm và một phần may mắn, cuối cùng họ sẽ thành công.

Tính cách của các nhân vật trong phim có lẽ không quá xa lạ với dân trong nghề. Nhưng đối với góc nhìn từ những người trái nghề, chắc chắn họ sẽ nhận ra nhiều điểm thú vị, từ đáng yêu cho đến ngầu và “bựa” của những anh chàng IT.

Chúc các bạn xem phim vui vẻ.

Xem Phim Tại Đây.

Write Private Functions Not Private Methods


Khi một class có quá nhiều private method (được gọi là “Lớp tảng băng trôi” – Iceberg class) thì đó là dấu hiệu cho biết class đó có thể đang làm hơn 1 nhiệm vụ (responsibility). Vì vậy việc tách (extract) những private method đó ra class khác giúp lớp sẽ tuân thủ theo nguyên tắc Single Responsibility Principle. Qua đó, việc loại bỏ các private method còn giúp ích cho các lập trình viên trong việc viết Unit Test.

Cùng xem bài viết của Jared Carroll để rõ thêm về điều này.

During refactoring, private methods are created in order to:

  • Eliminate duplication within the class
  • Clarify confusing and/or complex fragments of related code (Extract Method)

These are both great refactorings, but be cautious of classes with an excessive amount of private class or instance methods. This is a smell that often indicates a class is doing too much work. Help maintain cohesion by refactoring private methods into separate objects. In this post, we’ll look at a way of writing private methods that encourages future extraction.


An iceberg class is a class that has more private methods (3? 5? 10?) than public methods. Private methods are often an indication of additional, hidden responsibilities. By adopting a functional style, private methods can be easily extracted into separate objects.

A private function is a private method that:

  • Calculates its result only from its arguments
  • Does not rely on any instance (or global) state


Below is a modified portion of the User model from a Ruby on Rails Tutorial sample app.

class User < ActiveRecord::Base
  attr_accessor   :password
  attr_accessible :name, :email, :password, :password_confirmation

  before_create :encrypt_password

  # public methods...


  def encrypt_password
    self.salt = make_salt
    self.encrypted_password = encrypt(password)

  def make_salt

  def encrypt(string)

  def secure_hash(string)

When a User is created their salt and encrypted password are set. Four private methods are used to implement this.User#encrypt_password is called by ActiveRecord, which means we have no control over sending arguments to it, so it will have to remain a method. Of the remaining three private methods, only one User#secure_hash, is a function.

Let’s refactor the other two into functions.

class User < ActiveRecord::Base
  # same implementation as above...


  def encrypt_password
    self.salt = make_salt(password)
    self.encrypted_password = encrypt(salt, password)

  def make_salt(password)

  def encrypt(salt, password)

  def secure_hash(string)

Encryption doesn’t feel like a User responsibility, so let’s extract it into a separate object.

class Encryptor
  def self.make_salt(password)

  def self.encrypt(salt, password)

  def self.secure_hash(string)

  private_class_method :secure_hash

We’re still left with one private class function. This seems ok because it’s related to Encryptor‘s core responsibility. Also, Encryptor.make_salt is not a function because it relies on global state,; this will make unit testing it difficult. Let’s punt on fixing that for now, because this class is already an improvement.

Finally let’s update User by having it collaborate with our new Encryptor class.

class User < ActiveRecord::Base
  # same implementation as above...


  def encrypt_password
    self.salt = Encryptor.make_salt(password)
    self.encrypted_password = Encryptor.encrypt(salt, password)


There are two disadvantages of extracting private functions into new classes:

  • Naming the new abstraction is difficult because it’s often a verb and not a noun
  • The message sender now has to now instantiate a class and send it a message

Our above User refactoring resulted in a somewhat awkward, doer class (Encryptor). I also only used class methods in Encryptor, essentially creating a namespace of functions. This eliminates the need to instantiate a separate class, but it doesn’t feel very object-oriented.

I don’t see a solution for either of these two disadvanages. They’re by-products of modeling software in an object-oriented way.


Cohesive, single responsibility classes are easy to understand and reuse. Private methods are one indication that a class is beginning to take on additional responsibilities. By writing private methods in a functional style, you take the first step in preserving a class’s true responsibility.