Thói quen lập trình tốt?

Tớ không ghi nguồn vì từ những cái này là lụm lặt và tích cóp lại thôi, ai thích thì cứ dùng, ai cần copyright thì để comment lại tớ add

  • luôn luôn ghi rõ chú thích ở những đoạn code phức tạp tốt nhất là ghi rõ công việc mà đoạn code đó sẽ thực hiện
  • nếu muốn biết rõ thì cứ bắt tay vào làm, chương trình càng lớn càng tốt
  • thừa kế Coding Standard và thêm vào đó kinh nghiệm bản thân thì việc lập trình sẽ dễ dàng hơn
  • Khi tạo biến số mới nhớ cho liền giá trị (initializing), đừng để không. Thí dụ int x=0;
  • Nguyên tắc lấy từ sách “The Mythical Man-Month”: dục bỏ lần viết lập trình đầu tiên (phan to throw one away). Thí dụ như bạn “hack” được một giải pháp chạy được, tiếp theo bạn nên sửa chữa thêm thắt để nó chạy thật an toàn và hiệu quả bằng các phương pháp như “refactoring”: lấy code ra làm hàm chung để xài lại, thêm lệnh try … catch, v.v.
  • Nguyên tắc lấy từ sách “Fundamentals of Software Engineering”: chia để trị (separation of concerns.) Thí dụ như mình phải chia mã làm GUI (giao diện)tách riêng khỏi mã lô gíc (như mã đóng mở tệp, giải thuật) Nếu làm bùi nhùi một đống sẽ rất khó sửa lỗi (debug), sau này không dễ chuyển sang môi trường khác (linux, Mac OS) được. Tốt hơn hết là viết giao diện (với C++) với software như wxWindows có thể compile với tất cảc các OS trên, còn phần logic thì viết bằng C++ và các thư viện chuẩn, dùng một lớp (layer) mỏng để chuyển std::string sang wxString và ngược lại.
  • Code 1-2 dòng rồi compile ngay, không đợi code 5,6 dòng rồi mới compile. Có hai cái lợi: nếu compile không chạy mình biết mình vừa làm gì sai, rồi undo và sửa liền, nếu viết quá 6 dòng nó ra một chặp lỗi chẳng biết hư ở chỗ nào. Lợi thứ hai là ở chỗ khi code mà bạn thấy code hơi có vẻ lặp đilặp lại là bạn tìm cách refactor và cho nó ra hàm riêng liền, còn để lâu bạn sẽ lười vì code chạy mà, sửa làm chi.
  • Đọc càng nhiều sách về mọi thể loại lập trình càng tốt, không nở bề ngang cũng nở bề dọc. Và tập đọc bằng tiếng Anh, và tập sử dụng chúng trong các forum càng nhiều càng tốt. Tôi nghĩ các từ vựng tiếng Anh cũng không nhiều, cùng lắm là vài trăm từ là cùng. Các tác giả C++ chẳng hạn, đa phần là họ nặng về kỹ thuật, nên khỏi sợ đụng nhằm thứ văn chương hoa lá cành. tôi nhớ hồi xưa tôi đọc quyển “Oh! Pascal” phải rị mọ dịch từng chữ, dần dần tôi đọc theo “context” (hiểu đại khái ý chính) và không dùng tự điển nữa.
  • Biết khi nào phải dừng (lấy từ sách the Pragmatic programmer) : software chẳng bao giờ hoàn toàn, và bao giờ bạn cũng có ý tưởng mới lạ trong đầu để cải tiến thêm. Nhưng tới một lúc nào đó bạn phải quyết định dừng lại, nếu không sản phẩm sẽ không chào đời! Có cái lợi là “feature” bạn muốn thêm vào sẽ để dành lần sau, gọi là “new feature”, có hai lý do khiến “biết khi nào phải dừng” áp dụng cho trường hợp của cá nhân tôi. Công việc tôi làm ở sở là thiết kế, viết code, test, và cả bảo trì luôn, tôi tự đùa là “one man band” như trong ban nhạc karaoke một người vậy. Nếu tôi không dừng thì users sẽ đòi nhiều tiết mục mới hoài. Lý do thứ hai trở lại ý chính của tác giả chủ đề này là “design by contract”, là làm đúng theo những gì đã quy ước giữa mình và khách hàng, không hơn không kém. (Họ có trả thêm tiền đâu mà làm thêm?) Nhiều khi trong khi code mình thấy có feature này hay, nên thêm vào ngay, tuy nhiên thêm vào vài ba cái như vậy trong một ngày sẽ làm giảm tiến độ của việc đang làm, và tạo khó khăn cho người sẽ thử code sau này.
  • Rigor and Formality: sự cứng nhắc, rất khuôn mẫu, đến độ rất hình thức và gọn ghẽ như đang chứng minh cho một định lý vậy. Rigor, tưởng chừng như đối chọi với sự sáng tạo (creativity), thực ra lại là một bổ túc quan trọng. Nó làm lập trình viên tin tưởng thêm vào các sáng tạo của mình, một khi các sáng tạo này đã trải qua các thử thách như test cases chẳng hạn. Không cần lúc nào cũng phải cần chứng minh software của bạn, chỉ khi nào bạn viết các giải thuật khó như tree, hash, v.v. Rigor và formality còn áp dụng vào software process nữa,chẳng hạn như việc viết tài liệu hướng dẫn cách sử dụng, phải biết viết sao cho chặt chẽ. Ta cũng có thể viết report trong đó ghi lại chặt chẽ các bước đã thực hiện phần mềm, ưu khuyết điểm để rút king nghiệm cho các projects tới.
  • Tip: Tránh sử dụng dạng struct mà các field trong đó là dạng object, các thứ trong đó nên sử dụng dạng bộ nhớ tĩnh.

    Lý do: Nếu như bạn sử dụng dạng object thì việc gọi ctor và dtor của các object đó cũng được thực hiện mỗi khi struct đó được cấp phát và giải phóng. Bình thtường bạn có thể sử dụng phép gán cơ bản
    [sourcecode language=”cpp”] B = A; // okie mọi thứ đều chạy tốt
    Nhưng bạn hãy xem đoạn mẫu sau:
    struct NMSTRUCT{
    wstring s1;
    wstring s2;
    int i;
    }
    NMSTRUCT *nm1 = new NMSTRUCT;

    NMSTRUCT nm2;

    nm1->s1 = _T(“nm 1 msg”);

    nm1->s2 = _T(“nm 2 msg”);

    memcpy(&nm2, nm1,sizeof(NMSTRUCT));

    delete nm1; cout < < nm2.s1 << endl << nm2.s2<<endl;[/sourcecode]
    Chương trình chạy tới cout < < nm2.s1 << endl << nm2.s2<<endl; thì sẽ bị lỗi.

    Nguyên nhân là vì khi memcpy copy y nguyên dữ liệu (địa chỉ bộ nhớ) từ nm1-> nm2 vậy nên nếu ta delete nm1, s1 và s2 của nm1 đã bị gọi dtor, thì việc truy xuất s1 và se từ nm2 sẽ bị lỗi (access violate)

  • Tip:Khi run một console app mà UNICODE và _UNICODE được define thì bạn sẽ bị cái lỗi Warning: Destroying non-NULL m_pMainWndn

    Và đây là nguyên nhân: http://www.voidnish.com/articles/ShowArticle.aspx?code=mfcprogflow
    Cách giải quyết theo cá nhân tôi là: Vẫn define _UNICODE và UNICODE lên nhưng k0 đặt entrypoint wWinMainCRTStartup