Giaosucan's blog - Chia sẻ kiến thức theo cách bá đạo

Ticker

20/recent/ticker-posts

Sự tích Cuder

Chuyện kể rằng, ngày trước có một chàng sinh viên mới ra trường, chàng thích code từ ngày còn học phổ thông, nên được một công ty phần mềm rất to tuyển vào làm việc với vị trí rất nhỏ.
Với phương châm “OT vì đam mê”, chàng làm việc rất cần cù, không ngại OT ngày đêm để hoàn thành task được giao. Sếp mừng lắm “ Kiếm được 10 chú như em này thì lời to, trả lương thấp làm trâu, lo gì mà không đạt doanh số”
Năm ấy, đơn vị biz trúng dự án to, lại được sếp hứa tăng lương sau khi hoàn thành dự án, nên chàng mừng lắm, quyết tâm phen này phải lên level


Ai ngờ, do đội dự án lười log timesheet, nên anh PM estimate sai toét, dẫn tới anh em OT, ON triền miên mà làm không hết task.
Đêm ấy, chàng phải ON tại công ty để code, nhìn đống code cả trăm KLOC lộn xộn, chàng không biết làm sao, chỉ biết ôm bàn phím khóc hu hu
Bỗng lúc đó, một ông cụ hiện ra cười hiền từ
“ Ta là Bụt đây, làm sao con khóc ??“
Chàng đang khóc, bỗng cười hô hố
“Ngài là Bill Gates, founder của Microsoft, hồi sinh viên đi cài Win dạo, con xài chùa phần mềm của ngài suốt, mua đĩa có 8K/cái”
Bill Gate nghe xong thở dài “ Phần mềm windows cả triệu dòng code, thế mà Việt nam bán có 8K, nếu ta ngồi ở Việt Nam chắc cũng thành thằng cài win dạo như nó”
Tuy tức giận, nhưng Bụt Gate vẫn cười như mùa thu tỏa nắng
“Con gặp issue gì thì report, để ta xem có solution gì ko”
“ Con đang làm phần mềm quản lý ngân hàng, ban đầu chức năng còn ít, nên số LOC ít, nhưng giở khách hàng Change Requirement liên tục (CR), số LOC ngày càng nhiều, nhờ ngài review code giùm con”
Bụt Gate review code trong vòng 1 nốt nhạc bỗng cả giận mắng:
“Ngươi code theo phong cách gì vậy”
“Con code theo phong cách Viet Style, hãy code theo cách của bạn, con thích thì con code thoai”
Bụt Gate nghe xong chỉ biết cười méo miệng
“Trong phát triển phần mềm, KH sẽ change requirement liên tục, code của con phải được viết sao cho dễ đọc, dễ test, và đặc biệt phải có khả năng mở rộng
Ta nhìn code của con đã thấy con mắc phải những sai lầm nghiêm trọng 5 không, 3 thích, nói ngắn cho nó vuông là “Code quá lầy

  • Không quan tâm đến coding convention, đặt tên biến vô tội vạ a1, a2, đọc hiểu chết liền
  • Không quan tâm đến module hóa, chỉ cần code chạy được là ok, nhìn mớ code hỗn độn như đống rác
  • Không có comment, code theo phong cách vô chiêu thắng hữu chiêu, biến ảo vô cùng, đọc code xong tức thổ huyết mà chết
  • Không chịu review code, code xong vác ra chạy luôn, review code tốt có thể giảm thiểu được 20% bug
  • Không nghĩ đến optimize code, không sử dụng cấu trúc dữ liệu phù hợp dẫn tới tốn memory, low performance
  • Thích code như Công Phượng đá bóng, thể hiện, lạm dụng design pattern, dẫn tới xử lý đơn giản nhưng code như rồng bay phượng múa
  • Thích Google search and Copy paste, mà không hiểu hết xử lý của code đó
  • Thích cắm đầu code ngay, mà không nghiên cứu kĩ giải pháp, tìm hiểu requirement, làm gì cũng phải có “dạo đầu”

Nay ta hướng dẫn con 1 nguyên tắc cơ bản trong coding gọi là SOLID, nếu áp dụng thuần thục, ta thề hứa và đảm bảo con sẽ thành “thánh code

Single responsibility principle (S)

Mỗi class hoặc một method thì chỉ thực hiện một xử lý duy nhất
Ví dụ class DBContext thực hiện xử lý CRUD

public class DBContext
{
public void Create() {}
public void Update() {}
public void Retrieve() { }
public void Delete() { }
}

Nếu class này phải thực hiện những xử lý khác nữa thì cần phải tạo class khác, tránh việc thêm quá nhiều vào 1 class khiến class sẽ bị phình to, class kiểu này gọi là God Object
Tương tự cho việc viết method, mỗi method thực hiện 1 xử lý duy nhất ví dụ hàm run() thì thực hiện xử lý chạy, nếu có thêm xử lý nhảy thì phải viết thêm hàm dance()

Open/closed principle (O)

Các class,method nên được thiết kế sao cho có thể dễ mở rộng, nhưng không phải sửa đổi nội dung của class, method đó
Có thể hiểu qua ví dụ sau
Class Idol có xử lý catwalk() là một chức năng của object Idol, nếu có object NgocTrinh và HoNgocHa cũng là một idol nhưng ngoài khả năng catwalk() ra còn có khả năng dance(), và sing() thay vì add method trên vào class Idol thì tạo ra class mới kế thừa class Idol, override lại method catwalk() nếu như NgocTrinh và HoNgocHa có cách catwalk khác nhau
Như vậy class Idol sẽ không phải sửa đổi và con sẽ không phải test lại class này, hạn chế tối đa side effects

public class NgocTrinh : Idol
{
public override void catwalk() { };
public void dance() { };
}

Liskov substitution principle (L)

Đây là nguyên tắc do nhà khoa học máy tính Barbara Liskov sáng tạo ra, nội dung của nguyên tắc này nếu đọc trên Google chắc sẽ con sẽ rất “bối rối” vì khó hiểu
Object của lớp kế thừa có thể thay thế lớp cha nhưng không được thay đổi behavior của lớp cha.
Tuy nhiên qua ví dụ cụ thể sẽ hiểu
class Idol
{
public void catwalk()
{
// catwalk bằng 2 chân
};
}
class NgocTrinh : Idol
{
public override void catwalk()
{
// catwalk bằng 4 chân
};
}
Object Idol là người mẫu thực hiện catwalk() bằng 2 chân, tuy nhiên đối tượng em NgocTrinh lại override catwalk bằng 4 chân thì đây là một strange behaviour, vì e NgocTrinh là Idol và cũng là người nên đi lại bằng 4 chân là vi phạm nguyên tắc Liskok, hay vi phạm đến tính đa hình của đối tượng

Interface Segregation Principle (I)

Thay vì dùng 1 interface lớn, ta nên tách thành nhiều interface nhỏ, với nhiều mục đích cụ thể
Ví dụ
interface IIdol {
public void catwalk();
}
Đối tượng NgocTrinh, HoNgocHa đều implement interface IIDoil nên phải code xử lý method catwalk
class NgocTrinh implements IIdol {
public void catwalk () {
// ....walking
}
}
class HoNgocHa implements IIdol {
public void catwalk () {
// ....walking
}
}
Nếu như Interface IIDol được add thêm các method như dance(), sing() thì class NgocTrinh, HoNgocHa cũng phải implement thêm những method tương ứng dẫn tới việc dư thừa vì NgocTrinh chỉ biết dance() chứ không biết sing() và ngược lại.
Tưởng tượng nếu con có 100 class đang implement một interface IIDol, nếu thêm một method vào interface IIDol đó thì sẽ phải sửa toàn bộ 100 class còn lại.
Hơn như việc này sẽ làm interface IIDol sẽ phình to ko hiệu quả cho việc maintain, do đó phải tách ra thành 2 interface nhỏ hơn (Idance, Ising) để tiện việc maintain như sau
interface IDance {
public void dance();
}
interface ISing {
public void sing();
}
class NgocTrinh implements Iidol, Idance {}
class HoNgocHa implements Iidol, Ising {}

Dependency inversion principle

Đây là nguyên lý khó hiểu nhất trong Solid, dễ gây loạn chưởng nhất cho coder
Có thể hiểu qua ví dụ sau

  1. Tỉ phú Hoàng Kiều kí hợp đồng làm ăn với Khắc Tiệp
  2. Khắc Tiệp chuyên cung cấp chân dài theo tiêu chí của Hoàng Kiều
  3. Tuy nhiên Khắc Tiệp do chạy sô nhiều nên thỉnh thoảng ko cung cấp đúng như yêu cầu của Hoàng Kiều. Hoàng Kiều lỡ kí hợp đồng rồi phụ thuộc vào Khắc Tiệp nên bó tay 
Example
class HoangKieu {
private KhacTiep supplier;
public string getChanDai() {
supplier = new KhacTiep();
chandai = supplier.cungCapChanDai(NgocTrinh);
return chandai;
}
class KhacTiep {
public string cungCapChanDai (string idol) {
if (idol.equals(“NgocTrinh”)){
fake = “Fake”; // tráo hàng
}
return fake;
}
Ở vị dụ trên, module cấp cao HoangKieu phụ thuộc vào module cấp thấp KhacTiep, method cungCapChanDai thay đổi (ví dụ thay đổi kiểu tham số) dẫn tới phải sửa đổi method getChanDai ở module Hoang Kieu, giảm khả năng bảo trì
Theo nguyên tắc này thì sẽ thiết kế như sau

  1. Hoàng Kiều làm việc qua một trung gian (interface) Đại Lý
  2. Hoàng Kiều đưa yêu cầu cho Đại Lý cần cungcapChanDai(NgocTrinh)
  3. Đại Lý tìm KhacTiep để cung cấp nếu không thỏa mãn thì tìm nhà cung cấp khác ví dụ QuangHuy
viết code như sau
interface DaiLy { public string cungCapChanDai (string idol); }
class KhacTiep implements DaiLy {
}
class QuangHuy implements DaiLy {
}

class HoangKieu {
string getChanDai(DaiLy data) {
chandai = data.cungCapChanDai(NgocTrinh);
}
}
Như vậy HoangKieu chỉ việc truyền object là KhacTiep hay QuangHuy vào method getChanDai là có được chân dài như mong muốn mà ko phải sửa đổi
“Trên đây là 5 nguyên tắc cơ bản của coding, mà bất kí coder nào cũng cần hiểu rõ, con hãy nhớ lấy”
Bụt Bill Gate sau khi nói xong thì hóa khói bay mất, để lại chàng coder ngồi thẫn thờ, nhìn lại đống code của mình, chàng đã hiểu ra chỉ còn cách đập đi làm lại. Nhưng dead line đã đến gần, không còn thời gian nữa, dự án cuối cùng fail thảm hại, giấc mộng lên level cũng tan biến.
Từ đó, vào mỗi đêm, người ta lại thấy 1 thanh niên đầu tóc bù xù đi lại trong dãy hành lang, chàng than thở khóc những tiếng kêu ai oán vì những sai lầm của mình, chàng hóa thành con cú mèo kêu những tiếng kêu “Cú, cú ,.. der”
Và Cuder có từ ngày đó.

Đăng nhận xét

0 Nhận xét