Home Blog Page 129

Xin chào PureMVC

xin chào puremvc

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Ahi hi :))  khọc khọc 😀 Tôi viết bài thấy mấy anh em chê dễ quá nên thôi tôi giành 1 ít thời gian viết một vài thứ nâng cao cho các anh em đỡ kêu vậy. Bài này ta sẽ tìm hiểu 1 design pattern khá là khó xài, nhưng một khi đã làm chủ nó thì cuộc đời ơi đẹp lắm. Bạn ghi vào CV của bạn là tôi biết PureMVC này, nhận tôi đi nếu không công ty sẽ mất 1 nhân tài đó  =)) Tôi đùa thôi. Đôi khi đi xin việc, bạn cũng cần hài hước mà chém gió cho nhà tuyển dụng họ sợ  😀 Thôi tôi không khoác lác nữa, dù chém gió hay như nào thì bạn cũng phải biết code nạ 😀

  Lập trình hướng chức năng đang thống trị mảng UI với Pure Views

  Mô hình MVC trong php là gì? Hướng dẫn chi tiết

Đầu tiên tôi giới thiệu PureMVC là 1 design phát triển cũng na ná MVC, trong đó:

M = Model(Data)

V= View(Màn hình hiển thị)

C = Controller(Điều khiển).

Nhưng thằng PureMVC nó có các kết nối lỏng lẻo hơn MVC nhiều. Việc tạo ra các kết nối lỏng lẻo như vậy sẽ giúp cho việc phát triển ứng dụng dễ dàng chỉnh sửa, đại tu các thứ. PureMVC hỗ trợ cho actionscript, C++, java, python, ruby.. Nhiều lắm. Anh em lên đây mà đọc nhé:

http://puremvc.org/

Ở  C++, chúng ta có thể tải code từ đây và build tẹt ga cho window hay các nền tảng khác như linux, Macintosh.. Trích file howtobuild từ source code:

Supporting compilers:
=====================
+ Microsoft Visual C++ 6.0 7.0 8.0 9.0 10.0
+ Minimalist GNU for Windows G++ 3.4.5, 4.x.x (MinGW32)
+ GCC for Linux, MacOS: 3.4.5, 4.x.x
+ Embarcadero C++ Builder 6.21 (Borland C++ Builder in old-name)
+ Digital Mars C++ 8.42n

Supporting operation systems:
=============================
+ Microsoft Windows XP SP3, Micorosoft Windows 7
+ Linux (Fedora 7, CentOS 5.2 64 bit & 32 bit)
+ Macintosh (Tiger X 10.4, Leopard 10.5)

Terminology:
============
bcc: Borland C++ Compiler / Embarcadero C++ Compiler
vc: Visual C++ Compiler
dmc: Digital Marcs C++ Compiler
ic: Intel C++ Compiler
mgw: Minimalist GNU for Windows (MinGW32)
gcc: GNU C++ Compiler

Vậy, anh em làm ứng dụng cho nhiều nền tảng (cross platform) cứ yên tâm là sẽ support tận răng nha :))

Rồi, bây giờ tìm hiểu tiếp các thành phần của framework này.

Tôi tạm lấy cái hình từ file tài liệu của các ổng code, trông nó bay bướm như này:

ac.PNG

Anh em sẽ chiến từng thằng một 😀

  • Proxy: là thành phần của Model. Ổng này là thành phần chuyên xử lý transactions data. Ông request lấy data, ổng lưu, ổng xóa… Ổng này việc đơn giản là thế.Ví dụ ổng request lên server lấy thông tin của 1 user. Sau đó ông ấy lắng nghe data trả về, rồi ông ấy save data này lại vào lớp VO = Các lớp public chứa data của chúng ta. Vậy bạn nhớ cho tôi là Proxy và các VO mà bạn định nghĩa sẽ nằm cùng thư mục là Model.
  • Mediator: là thành phần xử lý cho View. View là gì? Là khung nhìn, gồm giao diện chứa nút bấm, ô nhập… Các thứ mà người dùng có thể click, chạm, sờ, đập đá.. :)) Ổng vẽ các view lên. Ổng nhận các action này, rồi ông gửi action này cho các thằng khác thông qua sendnotification. Hiểu đơn giản là bắn tin nhắn cho ông nào thích thì cứ nhận mà xử lý. Mọi xử lý thuộc hàm handleNotification(INotification* notification). Ông lắng nghe các notification của những thằng khác, ông xử lý. Ở lớp này anh em nhớ có hàm: onRegister: hàm này để đăng ký lắng nghe các action.
  • Command: là thành phần của Controller. Nghe cái tên là anh em nó chuyên xử lý. Ông này có hàm execute(INotification* notification) để thực thi các notification nó bắt được. Và nó cũng có thể gửi request cho các thành phần khác xử lý. Đơn giản nó có nhận có gửi xử lý notification.

Các bước mô tả như sau:

  1. Ứng dụng sẽ bắt đầu khởi động với 1 facade. Facade khá trừa tượng, nó là 1 đối tượng quản lý ứng dụng của chúng ta, nó như cái xương sống vậy. Chương trình sẽ bắt đầu từ đây. Ví dụ ta hay đặt tên: ApplicationFacade
  2. Facade sẽ gọi tới hàm startupCommand. Lớp này để khởi động ứng dụng. Khi ta viết với C++, ta sẽ gọi đối tượng facade->statup() và hàm starup sẽ gửi notification cho  startupCommand.
  3. StartupCommand sẽ tiến hành đăng ký các proxy và các mediator cần sử dụng trong chương trình thông qua hàm registerProxy(yourproxy) và hàm registerMediator(yourMediator). Đồng thởi ở lớp này thì ông ấy sẽ remove cái command startup luôn. Ví dụ: removeCommand(ApplicationFacade::STARTUP). Sau khi đăng ký xong thì các thành phần này sẽ im lặng và lắng nghe các notificaiton để xử lý. Ông có thể bắn 1 cái notificaiton bật 1 cái view lên, chẳng hạn yêu cầu mở 1 cái view menu chương trình. Mọi thứ của startupCommand đều xử lý ở hàm StartupCommand::execute(INotification* notification). Các message được định nghĩa ở lớp ApplicationFacade.
  4. Application Mediator sẽ đăng ký các tiến trình của mediator
  5. Các process Mediator này sẽ đăng ký View và gửi message để load data.
  6. Facade sẽ nhận các notification này để pass data vào command.
  7. Data command sẽ lọc các notification này và gọi proxy load data.
  8. Proxy sẽ gửi các thông báo cho View thực hiện load data, Mediator sẽ xử lý việc này.
  9. Proxy sẽ gửi các notificaiton cho Mediator xử lý.

Cơ bản là như thế. Trong các bài sau tôi sẽ demo bằng visual Studio C++ cho các bạn dễ hình dung. Anh em cứ đọc thêm tài liệu nếu chưa hiểu lắm. Và bắt đầu cài đặt để code thì sẽ hiểu ngay 😀

Happy

Bài viết gốc được đăng tải tại quynhlaptrinhc.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Đàm phán và thương lượng không khó như bạn nghĩ?

đàm phán
đàm phán

Đàm phán và thương lương đều là những kỹ năng quan trọng. Thông qua việc đàm phán, thương lượng, các giá trị của bản thân bạn sẽ được bộc lộ một cách tốt nhất. Đối với các freelancer IT, Senior Developer hay bất kỳ vị trí tuyển dung it nào, bạn cũng cần kỹ năng này.

Thế nhưng, nhiều người luôn e ngại về thể hiện mình. Hoặc thậm chí là họ chưa thật sự nắm bắt tốt kỹ năng này. Cùng TopDev tìm hiểu về bí quyết đàm phán và thương lượng thật chất lượng.

Áp dụng Quy tắc 51/49

Hiểu một cách đơn giản, quy tắc này cần bạn đảm bảo mang lại ít nhất 51% giá trị thực tế cho một mối quan hệ.

Xem thêm các việc làm về tuyển dụng Data Scientist 

đàm phán
Đàm phán – Pic1

Việc xây dựng và thiết lập một mối quan hệ đòi hỏi rất nhiều yếu tố. Đó có thể là giao tiếp giữa freelancer it với các khách hàng doanh nghiệp; trao đổi về các lợi ích; đàm phán những rủi ro – thách thức có thể đối mặt,…

Bạn hãy thật linh hoạt, thông minh và cân nhắc xem xét và cố gắng mang lại cho đối tác nhiều lợi ích hơn. Điều này có ý nghĩa quan trọng để duy trì một mối quan hệ lâu dài.

Chấp nhận “đứng thấp hơn 1 bậc” so với đối tác sẽ là một chiến lược thông minh.

Vì khi những gì bạn thỏa thuận giữa freelancer it với khách hàng có xảy ra những phát sinh bất cập từ công ty. Và việc chịu trách nhiệm sẽ không hoàn toàn là do bạn. Và lúc này tiếng nói của bạn có sức nặng hơn.

Dấu ấn lớn từ việc tạo lập các giá trị

Khả năng thuyết phục người khác là một kỹ năng quan trọng cần trau dồi. Và nó ảnh hưởng rất nhiều đến các mối quan hệ của bạn.

Đàm phán gắn liền với mục tiêu, kế hoạch. Khi đó bạn đang đồng thời thể hiện giá trị của bản thân.

đàm phán
Ban cần quan tâm đến việc tạo ra các giá trị!

Xem thêm các việc làm NTQ Solution tuyển dụng

Thương lượng thành công hay không là do những cam kết về giá trị và những thành quả hiệu suất; sự cố gắng mà trước đó bạn có được. Một freelancer IT cần cho nhà tuyen dung it thấy được bạn đã trưởng thành ra sao, các dự án bạn thực hiện, kỹ năng  -kinh nghiệm của bạn thế nào,…

Khi đàm phán và thương lượng, bạn phải thật bình tĩnh.

Đây là cơ hội tốt để bạn thể hiện tố chất và năng lực lãnh đạo, đàm phán. Hãy tập trung vào việc phân tích và giải pháp.

Bạn phải thể hiện cho họ thấy những mặt hạn chế và đâu là cách thức tối ưu cho các vấn đề. Đặc biệt, hãy trao đổi khách quan và đừng để những cảm xúc tiêu cực lấn át buổi thương lượng của bạn.

Tìm ra điều gì sẽ khiến họ đồng ý

Dù bạn là một freelancer it với trình chuyên môn cao thì mục đích vẫn là làm hài lòng khách hàng thông qua các đề xuất.

Hãy thật sự tinh tế để tìm ra những điểm mấu chốt của vấn đề. Đừng tập trung nói và khai thác, phô bày về bản thân quá nhiều. Hãy trình bày những gì bạn nghĩ là cần thiết cho khách hàng; đúng với nguyện vọng tìm hiểu và hệ giá trị mà họ định hướng khai thác.

Từ cơ sở đó, bạn nên làm mọi cách để đối tác tham gia vào cuộc hội thoại của mình. Đồng thời, thử thách họ bằng các câu hỏi nhằm xác định chính xác hơn nhu cầu; mong muốn của họ một cách tốt nhất.

Lời kết

Đàm phán và thương lượng là cả một nghệ thuật vì nó không đơn giản thuộc về giới hạn giao tiếp. Một điều đáng lưu tâm là hãy đảm bảo là cả đối tác và bạn đều vui vẻ khi rời bàn đàm phán. Chúc cho các bạn sẽ có cuộc đàm phán và thương lượng thật thành công.

Có thể bạn quan tâm

Xem thêm Top Việc làm Developer trên TopDev

4 mẹo deal lương như ý với vị trí Product Manager

product manager là gì
4 bước để deal được mức lương như ý với vị trí Product Manager

Tác giả: Dr. Nancy Li

Giới thiệu

Một mức lương tốt sẽ khiến chúng ta cảm thấy vui vẻ hơn khi làm việc. Điều đó là chắc chắn! Nhưng không phải công ty hay vị trí nào cũng có thể cho bạn mức lương tốt như bạn mong muốn. Vậy nên để làm được điều đó, bạn nên có những kỹ năng deal lương để nói chuyện với nhà tuyển dụng. Nhất là ở vị trí Product Manager, đây được xem là kỹ năng cần thiết để có mức lương trong mơ với công việc của mình.

product manager
Deal lương tốt cho công việc Product Manager với những mẹo hay nhất

4 bước để deal lương thành công cho Product Manager là gì?

Research – tìm kiếm nhiều nguồn thông tin khác nhau

Hãy cố gắng tìm kiếm thật nhiều thông tin trên internet để tự nhận biết xem hiện tại với khả năng của mình có thể nhận được mức lương cao nhất là bao nhiêu. Và những nhà tuyển dụng đang sẵn lòng trả lương như thế nào cho ứng viên ở công việc Product Manager này. Bạn có thể tìm những thông tin này trên LinkedIn hoặc GlassDoor – những nền tảng cung cấp các thông tin về nghề nghiệp hot nhất hiện nay. Những người đang làm ở đó hoặc những người đã từng làm trong công ty sẽ cho bạn biết hiện rank lương hiện tại của công ty đang ở khoảng nào và cân nhắc.

Value – thành quả tạo được khi trở thành Product Manager là gì?

Hãy nói về những giá trị mà bạn có thể mang lại cho công ty khi tham gia vào các chương trình Product Manager tuyển dụng. Một sai lầm mà rất nhiều người mắc phải khi deal lương với nhà tuyển dụng, đó là họ chỉ chăm chăm nói về những gì đã làm được trong các năm trước, ở những vị trí cũ trong khi công ty cần bạn cung cấp về những gì bạn có thể làm cho công ty hơn.

  7 tips để tuyển được những Product Manager xuất sắc nhất!
  Cách tạo một portfolio ấn tượng cho Product Manager

Những mục tiêu mà bạn đặt ra khi vào làm ở đây là gì? Bạn có thể giúp công ty đạt được những gì? Các thành quả mà bạn làm được sẽ quyết định mức lương bạn có thể nhận được. Sẽ không có nhà tuyển dụng nào muốn trả lương cao cho người không mang lại nhiều giá trị cho công ty. Hãy chứng minh khả năng của mình ngay từ vòng phỏng vấn.

Highball offer của Product Manager là gì?

Lấy ví dụ, nếu bạn muốn được trả mức lương 100.000 USD, bạn đừng bao giờ nói với nhà tuyển dụng rằng bạn luong mong muốn của mình là 100.000 USD. Mà sẽ là 110.000 USD – 115.000 USD, cao hơn một ít so với mức lương bạn thật sự mong muốn. Khi đó, bạn và người phỏng vấn sẽ nói chuyện với nhau và sẽ chốt được số lương thực nhận ở khoảng giữa so với con số đó. Nếu bạn nói đúng mức mình muốn thì lương sau khi thương lượng sẽ thấp hơn.

Xem thêm các việc làm tuyển dụng product manager hấp dẫn tại TopDev

product manager tuyển dụng
Tận dụng tốt khả năng đàm phán giúp bạn dễ dàng nói chuyện với nhà tuyển dụng hơn

Sự tự tin

Đây cũng chính yếu tố quan trọng nhất, nhưng không phải ứng viên nào cũng làm được. Rất nhiều người cảm thấy sợ hãi và thiếu tự tin khi đàm phán, thương lượng, nhất là trong lúc deal lương. Do đó để thành công, bạn hãy rèn luyện và cố gắng làm tốt điều mà không phải ai cũng làm được này nếu muốn có được mức lương như mình mong muốn.

Xem thêm các việc làm KMS Technology tuyển dụng hấp dẫn tại TopDev

Trước đây tôi cũng từng không thích việc phải thương lượng như thế này, nhưng đến một ngày tôi đã thay đổi khi nhận ra rằng: đàm phán đồng nghĩa với ảnh hưởng. Khi bạn đàm phán thành công chính là bạn đã tạo được ảnh hưởng lên một người, một vấn đề nào đó. Hãy thật tự tin cho thấy khả năng của mình để khẳng định rằng mình xứng đáng với mức lương thưởng như thế! Đó là bí quyết của sự thành công.

  5 loại profile của các Product Manager là gì?

Kết luận

Để deal được mức lương như ý, ứng viên cần nắm được những bí quyết riêng để dễ dàng đạt được thành công. Dù không phải là tất cả nhưng một mức lương tốt chắc chắn sẽ khiến chúng ta cảm thấy vui vẻ và thỏa mãn hơn khi làm việc ở vị trí Product Manager.

Bài viết được transcript dựa trên video gốc

Có thể bạn quan tâm:

Xem thêm việc làm tuyển dụng product manager hấp dẫn tại TopDev

PHP 8.0 có những tính năng gì mới?

PHP 8.0 có những tính năng gì mới?

Bài viết được sự cho phép của tác giả Lê Chí Dũng

PHP 8.0 là một bản cập nhật lớn của ngôn ngữ PHP. Nó chứa nhiều tính năng và tối ưu hóa mới bao gồm JIT, named arguments, union types, attributes, constructor property promotion, match expression, nullsafe operator và các cải tiến trong kiểu hệ thống, xử lý lỗi và tính nhất quán.

JIT (Just in Time)

JIT được cải tiến hơn và trong PHP 8 giới thiệu hai công cụ biên dịch JIT.
Và Tracing JIT, hứa hẹn nhất vì cho thấy hiệu suất tốt hơn khoảng 3 lần trên các điểm chuẩn tổng hợp và cải thiện 1,5–2 lần trên một số ứng dụng chạy dài cụ thể. Hiệu suất ứng dụng ngang bằng hoặc tốt hơn với PHP 7.4.

PHP 8.0 có những tính năng gì mới?
PHP 8.0 có những tính năng gì mới?

Đối số được đặt tên (Named arguments)

  • Chỉ xác định các thông số bắt buộc, bỏ qua các thông số tùy chọn.
  • Các lập luận không phụ thuộc vào trật tự và tự ghi lại.
/*** PHP 7 ***/
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

/*** PHP 8 ***/
htmlspecialchars($string, double_encode: false);

Ứng tuyển ngay các vị trí PHP tuyển dụng mới nhất trên TopDev

Thuộc tính (Attributes)

Thay vì chú thích PHPDoc, giờ đây bạn có thể sử dụng siêu dữ liệu có cấu trúc với cú pháp gốc của PHP.

/*** PHP 7 ***/
class PostsController
{
    /**
     * @Route("/api/posts/{id}", methods={"GET"})
     */
    public function get($id) { /* ... */ }
}

/*** PHP 8 ***/
class PostsController
{
    #[Route("/api/posts/{id}", methods: ["GET"])]
    public function get($id) { /* ... */ }
}

Khuyến cáo thuộc tính hàm dựng (Constructor property promotion)

Tiết kiệm viết mã hơn để xác định và khởi tạo thuộc tính.

/*** PHP 7 ***/
class Point {
  public float $x;
  public float $y;
  public float $z;

  public function __construct(
    float $x = 0.0,
    float $y = 0.0,
    float $z = 0.0,
  ) {
    $this->x = $x;
    $this->y = $y;
    $this->z = $z;
  }
}

/*** PHP 8 ***/
class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}
  10 Frameworks tốt nhất hiện nay cho PHP
  10 điều bạn cần biết về PHP7

Hợp nhất các kiểu (Union types)

Thay vì các chú thích PHPDoc cho sự kết hợp của các kiểu, bạn có thể sử dụng các khai báo kiểu liên minh gốc được xác thực trong thời gian chạy.

/*** PHP 7 ***/
class Number {
  /** @var int|float */
  private $number;

  /**
   * @param float|int $number
   */
  public function __construct($number) {
    $this->number = $number;
  }
}

new Number('NaN'); // Ok

/*** PHP 8 ***/
class Number {
  public function __construct(
    private int|float $number
  ) {}
}

new Number('NaN'); // TypeError

Biểu thức hợp nhau (Match expression)

Match là biểu thức mới tương tự như switch và có các tính năng sau:

  • Match là một biểu thức, có nghĩa là kết quả của nó có thể được lưu trữ trong một biến hoặc được trả về.
  • Các nhánh so sánh chỉ hỗ trợ các biểu thức một dòng và không cần break; để kết thúc lệnh.
  • Match không so sánh chặt chẽ.
/*** PHP 7 ***/
switch (8.0) {
  case '8.0':
    $result = "Oh no!";
    break;
  case 8.0:
    $result = "This is what I expected";
    break;
}
echo $result;
//> Oh no!


/*** PHP 8 ***/
echo match (8.0) {
  '8.0' => "Oh no!",
  8.0 => "This is what I expected",
};
//> This is what I expected

Toán tử Nullsafe (Nullsafe operator)

Thay vì điều kiện kiểm tra null, bây giờ bạn có thể sử dụng một chuỗi các cuộc gọi với toán tử nullsafe mới.

Khi đánh giá một phần tử trong chuỗi fails, quá trình thực thi của toàn bộ chuỗi sẽ bị hủy bỏ và toàn bộ chuỗi được gán là null.

/*** PHP 7 ***/
$country =  null;

if ($session !== null) {
  $user = $session->user;

  if ($user !== null) {
    $address = $user->getAddress();
 
    if ($address !== null) {
      $country = $address->country;
    }
  }
}

/*** PHP 8 ***/
$country = $session?->user?->getAddress()?->country;

Nhất quán lỗi cho các chức năng nội bộ (Consistent type errors for internal functions)

Hầu hết các chức năng nội bộ hiện ném Error exception nếu việc xác thực các tham số không thành công.

/*** PHP 7 ***/
strlen([]); // Warning: strlen() expects parameter 1 to be string, array given

array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0

/*** PHP 8 ***/
strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given

array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0

Tham khảo:

  • https://www.php.net/
  • https://wiki.php.net/rfc/jit

Bài viết gốc được đăng tải tại lcdung.top

Có thể bạn quan tâm:

Xem ngay những tin đăng tuyển dụng IT mới nhất trên TopDev

Sử dụng kiến thức SQL để công việc test dễ dàng hơn

Sử dụng kiến thức SQL để công việc test dễ dàng hơn

Bài viết được sự cho phép của vntesters.com

Chia sẻ của bạn Nguyễn Dương Hải về việc sử dụng kiến thức SQL trong quá trình làm test.

Mình không dám nói mình làm DB test nhiều. DB test, nếu làm hoàn chỉnh có rất nhiều phần bạn phải take care ví dụ như Performance của câu SQL, DB indexing, … Nhưng ở bất cứ dự án nào mình cũng đều cố gắng tìm hiểu Database structure của hệ thống. Mục đích chính là xem data flow đi như thế nào khi sử dụng feature trên UI, rồi từ từ mình cũng test một số feature bằng cách viết SQL. Sau đó mình học được những mẹo nhỏ để sử dụng kiến thức Database cua project và SQL để phục vụ cho công việc test của mình tốt hơn, tìm ra được nhiều case hơn. Mình xin phép nói về những trường hợp mình can thiệp vào DB và can thiệp thế nào để có hiệu quả tốt nhất.

1/ Test một feature khi những feature liên quan chưa sẵn sàng

Mình tin rằng bạn nào cũng đã từng gặp những trường hợp như thế này. Ví dụ:

  • Feature tạo đơn hàng đã xong.
  • Nhưng feature để xem danh sách đơn hàng vẫn chưa làm xong

Thông thường, ta cần có feature xem danh sách đơn hàng để một lúc kiểm tra 2 chuyện: tạo đơn hàng thành công và list đơn hàng đúng. Tuy nhiên, về mặt bản chất, tạo đơn hàng xong rồi thì chỉ cần kiểm trong database xem nó có lưu đúng field, đúng value không là được.

Thoạt nghe đơn giản nhưng bạn sẽ thấy có những feature rất phức tạp mà team bạn mất nhiều ngày mới làm xong. Nếu bạn làm tới đâu kiểm tới đó sẽ chỉ có lợi.

2/ Test Back End bằng cách check SQL

Ngắn gọn là, có những feature mà Back End chủ yếu là làm ra 1 câu SQL đưa data lên cho Front End, lúc đó là có gì in ra đó. Tìm hiểu câu SQL đó có thể cho bạn những ý tưởng thú vị để test, hoặc chỉ đơn giản là Analyze nó ra để xem họ có làm đúng logic không?

  ## trong SQL (2 dấu thăng) nghĩa là gì?
  Hướng dẫn giải bài toán phân bổ số lượng (thuật toán chia kẹo) trong sqlserver

3/ Fake data, clean data, dump initial data

Fake data

Đây là một trong những ứng dụng mà mình thích nhất khi đã hiểu tường tận DB của product rồi. Một ví dụ đơn giản, bạn test chức năng Sign Up, bạn phải test 10 case. Chỉ mỗi chuyện tạo 10 email để test thôi là mệt thở rồi. Nhưng mà, nếu bạn biết cách vào trong database, mình tin rằng bạn chỉ cần edit 1 field “email” trong 1 table nào đó là cái email ban đầu của bạn sẽ free ngay.

Lời khuyên:

  • Learn DB structure,
  • Học cách execute SQL,
  • Học câu lệnh Update.

Ví dụ:

UPDATEUserSET email=’dummy_email_1@gmail.com’, username=’dummy1’WHERE email = ‘hainguyentesting@gmail.com’

Tóm lại, bạn sẽ có thể sử dụng email hainguyentesting@gmail.com bao nhiêu lần tùy thích để nhận được email confirmation và test nó.

Clean data

Dùng trong trường hợp bạn muốn test environment của bạn được sạch sẽ để demo cho client, để test case empty data, hoặc có quá nhiều data rác làm bạn rối trí. Lúc này, chưa chắc trên Front End của bạn đã có feature REMOVE, mà nếu remove bằng tay thì cũng chết.

1 câu lệnh DELETE sẽ giúp bạn tiết kiệm rất nhiều thời gian:

DELETEFROM table_name [WHERE Clause]

WARNING! Để đảm bảo được tính thống nhất của data, bạn phải chắc chắn rằng bạn hiểu rõ database structure của product bạn. Ví dụ, nếu bạn muốn delete 1 row User đi thì trước tiên bạn phải remove những đơn hàng của user đó trong table don_hang trước. Nếu không database sẽ báo lỗi khi bạn cố gắng remove, hoặc là data bạn test sẽ không còn đúng nữa. Keep that in mind!

Dump initial data

Với những tình uống sau đây, bạn nên cân nhắc tạo ra 1 bộ data chuẩn và lưu giữ nó lại:

  • Bạn đang cần 1 lượng data lớn để test performance
  • Bạn không muốn client của bạn phải vào test khi chưa có 1 data nào trong website sau mỗi lần deploy.
  • Bạn đang cần 1 bộ data gồm nhiều case, giả sử như First Name có đủ kiểu từ chữ thường cho đến tiếng Hoa, Tiếng Hàn, “?!@#”,… để test layout.
  • Bạn đang muốn test case: structure của Dabase cũ sẽ được migrate sang thành structure mới khi server bạn start
  • Automation test case của bạn cần phải có 1 bộ data chuẩn, vì test case được thiết kế để kiểm tra đúng sai trên đúng bộ data đó! Là cái khác, sai 1 chút thì sẽ có 1 test case fail.

Với những trường hợp như trên mình đề nghị:

  • Bạn tạo ra 1 bộ data test với những data bạn cần. Khi tạo data, mình dùng câu lệnh INSERT, hoặc những website như https://www.mockaroo.com/ sẽ giúp bạn làm chuyện này tốt hơn. Học cách sử dụng những “data generator tool” không khó.
  • Nếu bạn muốn chắc ăn. Hãy tạo data trên UI, nhưng mình không khuyến khích vì nó sẽ tốn thời gian và phụ thuộc vào độ support của UI.
  • Sau đó, dump nó ra thành 1 file SQL. Trong SQL tools hoặc thậm chí là command line luôn có cách để làm vụ này
  • Khi nào cần, thì dùng chức năng backup file SQL ( có cả command line) để dump data ngược trở vào, đè lên toàn bộ data cũ.

Với cách này, mỗi lần test, bạn có thể ung dung test những case bạn cần với data có sẵn. Thậm chí bạn đã biết trước kết quả sẽ như thế nào nên việc testing cũng sẽ dễ dàng

WARNING! Những side effect sau đây cần phải được cân nhắc:

  • Team bạn đang thực hiện testing và data của họ bị xóa. Đặc biệt là client. Nếu bạn đang dùng chung 1 environment, thì phải có sự đồng thuận của tất cả mọi người
  • Update data test để có structure mới nhất.

Ví dụ, mình tạo ra 1 bộ data test, lúc đó database chỉ có field email, username và password thôi. Một thời gian sau, mình có thêm 1 field mới nữa là Name. Khi mình dump data test cũ vào, hệ thống báo lỗi.

Nếu team bạn có làm migration tốt, đó sẽ là một test case hay. Nhưng nếu team bạn không có kế hoạch làm nó, thì bộ data test của bạn phải được update structure thường xuyên, nếu không sao khi dump data, feature của bạn có thể chạy sai.

4/ Query real data sẽ giúp bạn thấy những điều thú vị

Tìm ra lỗi

Câu chuyện về cách đây 4 năm, mình làm cho 1 dự án Social Network. Team mình collect từ fanpage của những ca sĩ, username của những fan hâm mộ họ rồi blah blah. Lúc đầu, team mình cứ đinh ninh rằng username sẽ không có dấu “?” nên lúc thiết kế UI để render ra cái list này cũng chẳng support nó. Đến một ngày đẹp trời, mình query trên production và thấy chuyện này là có thể khi hệ thống mình capture được 1 vài user như vậy, sau đó thì fix Front End.

Analytic

Cũng trong dự án đó, client thường hay request team theo kiểu:

Nói cho tui biết trong 1 tháng qua có bao nhiêu đứa có 2000 fan trong hệ thống.
Có đứa nào trong 1 tháng tăng được 500 fan không?

Mình biết công việc này thường rơi vào Dev lead, nhưng nếu mình có thể sao lại không làm? Nếu bạn muốn đề xuất add thêm feature mới hoặc remove feature cũ, bạn sẽ cần data query như là 1 back up cho lập luận của bạn đó

Lời kết

Hy vọng sau bài viết này bạn có thể sử dụng kỹ năng SQL của mình đúng lúc và cân nhắc tất cả những hậu quả có thể có để có thể test một cách nhanh và hiệu quả nhất. Chúc các bạn thành công.

Bài viết gốc được đăng tải tại vntesters.com

Có thể bạn quan tâm:

Xem thêm IT Jobs in Vietnam for Developer hấp dẫn trên TopDev

System Design Cơ Bản – Phần 5: Indexes

Indexes

Bài viết được sự cho phép của tác giả Edward Thiên Hoàng

Có lẽ thuật ngữ “đánh index” đã quá quen với những ai làm việc với CSDL, đó là cách rất phổ biến để tăng tốc độ query của dữ liệu, khi dữ liệu Database ngày càng tăng và trở nên chậm dần đều theo thời gian. Mục tiêu của việc tạo Index là để tăng tốc độ trả về dữ liệu của một hoặc nhiều trường (rows) trên một bảng (table) cụ thể nào đó bằng cách tạo Index trên một hoặc nhiều cột (columns) của một database table.

  Những điều cần biết về z-index trong css
  4 ngôn ngữ phát triển game indie phổ biến

Để hiểu rõ hơn thế nào là Indexes ta hãy đến thử một nhà sách hay thư viện, thường các cuốn sách sẽ được phân chia theo các danh mục về nội dung như: sách nấu ăn, sách tiểu thuyết nước ngoài, sách tâm lý, sách lịch sử … Nếu ta muốn tìm kiếm một loại sách theo nội dung mong muốn thì chỉ việc tới cá kệ sách với nội dung tương ứng, nó sẽ nhanh hơn là tìm kiếm từ toàn bộ cả nhà sách từ. Hoặc ví dụ khác về các phần mục lục trong muốn cuốn sách, nếu ta muốn tìm nhanh đến “chương hồi” ta đang cần tìm kiếm hoặc đọc dở chỉ cần tra mục lục rồi tìm tới đúng trang chứa nội dung.

Index trong Database cũng giống như vậy, ví dụ ta có một table là Books chứa 4 columns là “book_title”, “writer”, “subject”, và “date_of_publication”, thường thì khách hàng sẽ thường xuyên tìm kiếm sách theo hai tiêu chí là tên sách và tác giả, do đó ta sẽ tạo Index cho hai column là “book_title” và “writer”. Database sẽ tạo ra một data structure riêng biệt chứa hai giá trị của toàn bộ nội dung (content) các cột đánh index và một con trỏ (pointer) để trỏ tới dữ liệu thật sự đang nằm ở Database. Như vậy, sử dụng index yêu cầu cần disk space để chứa cấu trúc của nó và Index cũng không làm thay đổi cấu trúc của table. Do vậy mỗi làm tìm kiếm dữ liệu thì Database sẽ tìm kiếm ở Index sau đó dựa vào con trỏ của Index để trả về dữ liệu thật.

Nhưng tại sao tìm kiếm trên Index lại nhanh hơn tìm kiếm trên Database, bởi vì Index luôn luôn sắp xếp dữ liệu để tối ưu nhất cho các thuật toánthực hiện việc tìm kiếm, còn dữ liệu Database thật thì luôn sắp xếp lộn xộn không có thứ tự nên không thuận tiện cho việc tìm kiếm. Mỗi Database sẽ có cách sắp xếp Index và thuật toán tìm kiếm Index khác nhau.

System Design Cơ Bản - Phần 5: Indexes

Tuy nhiên Index cũng không phải là một magic keyword, việc đánh Index cần thật cẩn trọng,
– Thứ 1: Việc tạo Index sẽ tốn disk space, do đó chỉ nên đánh những cột dữ liệu có dung lượng nhỏ, và sẽ không có ý nghĩa gì nếu đánh Index cột contents kiểu  chứa nội dung của một article vì lúc đó dữ liệu của Index sẽ to bằng nguyên cái table gốc.
– Thứ 2: Index thì ta cũng phải cần tạo ra nó, với một dữ liệu lớn sẵn rồi mà lúc này ta mới đánh Index thì việc tạo ra nó là một công việc rất tốn thời gian và tài nguyên hệ thống. Cho nên tốt nhất hãy lường trước ta tạo Index ngay từ khi dữ liệu còn nhỏ.
– Thứ 3: Việc dữ liệu được thêm mới sửa xóa (CUD) thường xuyên trên Table gốc thì Index cũng sẽ phải thêm mới sửa và sắp xếp lại, với một Table có dữ liệu lớn thì việc này cũng rất mất thời gian và nó sẽ làm chậm đi quá trình update hay create dữ liệu từ table gốc.

Do đó chỉ những Index thực sự cần thiết mới nên thêm vào và nên thường xuyên xem xét lại và xóa những Index không thực sự cần thiết. Và mục tiêu chính của Index đó là tăng khả năng đọc (read) của dữ liệu, do đó những Table dạng thường xuyên ghi nhưng ít khi được đọc thì tốt nhất không nên tạo Index, vì nó sẽ giảm hiệu xuất của việc ghi dữ liệu.

Theo medium

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Xin chào mọi người, lại là tôi Xuân Quỳnh đây 😀

trong bài trước, các bạn đã làm quen với kiểu con trỏ qua ví dụ với con trỏ kiểu char. Bài hôm nay anh em sẽ tiến hành đi vào vấn đề chính là viết 1 thủ tục printf thay thế.

  15 thư viện slider jquery miễn phí cho dự án website của bạn

  5 công cụ nguồn mở các thư viện cần biết

Chúng ta quay trở lại với thủ tục đã định nghĩa như sau:

void inramanhinh(char*caicaninra)

Bây giờ tôi sẽ giới thiệu 1 kiến thức mới, đó là thay vì bạn nhâp 1 ký tự thì bạn chơi với 1 chuỗi ký tự. Ví dụ chuỗi “abcd” chẳng hạn. Ký tự thì đặt trong nháy đơn, còn chuỗi thì nháy đôi các bạn nhé. Ví dụ tôi khai báo như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Ở đây tôi sử dụng 2 kiến thức mới:

Mảng: Mảng là gì? Là 1 kiểu tập hợp các phần tử đơn thành tập để tiện quản lý. Ở đây tôi dùng pc[10] nghĩa là tôi tạo mảng 10 phần tử, được đếm từ 0 tới 9. Tôi đồng thời gán luôn 3 giá trị đầu lần lượt là a, b, c. Sau này trở đi, để khai báo mảng bạn dùng cú pháp như sau:

[Kiểu dữ liệu] [tên của biến][Số lượng phần tử]

Ví dụ:

int mangnguyen[100];

float dayso[20];

Vòng for: Vòng for dùng để thực hiện những việc lặp đi lặp lại, để code bạn viết ngắn gọn lại. Nếu ví dụ trên không dùng vòng for, bạn cũng có thể in ra 3 dòng như sau:
Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Giả sử bạn có 100 chữ cái thì bạn viết ra 100 dòng :)) Vậy bạn đã biết ý nghĩa của vòng for như nào rồi đó.

Cú pháp vòng for như sau:

for (giá trị khởi tạo; điều kiện dừng; nếu đúng điều kiện dừng thì làm việc ở đây)

Tôi sẽ giới thiệu vòng for kỹ hơn vào các bài sau. Tạm thời bạn biết thế đã 😀

Khi cấp phát mảng 10 phần tử bạn hình dung bộ nhớ được phân phối như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Bộ nhớ gồm 2 phần, 1 phần đánh địa chỉ từ 0, trên hình tôi để dạng hexa. Phần 2 là giá trị nằm trên ô nhớ đó. Ở đây tôi dùng kiểu char, cho nên 1 ô nhớ có kích thước đúng bằng sizeof(char). Vậy bạn có 10 ô, được đánh số từ 0 tới 9. Vậy, nếu bạn muốn dùng con trỏ thì làm như nào. Tôi sẽ dùng con trỏ khởi tạo 10 ô tương tự trên nha, đảm bảo không hiểu không tính tiền luôn :))

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Ố ồ, nhìn có hoảng không các mem mới 😀 Tôi mà mới học tôi cũng hoảng. Nhiều cái mới quá. Ta tiến hành bóc tách từng thứ 1.

Đầu tiên là dòng thứ 2:

#include < stdlib.h >

Đây cũng là 1 thư viện mới. Tôi dùng hàm malloc cho nên tôi cần thư viện này. Nếu bạn build bằng gcc mà quên không include vào thì nó cũng báo cho bạn biết 😀

Dòng này là chủ đạo:

pMangChu = (char*) malloc(sizeof(char) * 10);

Trông nó hoa vện như con giun ấy nhỉ. Để hiểu câu lệnh trên, ta xem hàm nguyên mẫu của các ông bên UK, US định nghĩa nó như nào nhé:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Nguyên mẫu tôi lấy từ trang này.

Bạn dịch hộ tôi cái. Còn tôi sẽ diễn giải đơn giản như này. Bạn thấy từ khóa void. Bạn thấy quen, nhưng ở đây thêm dấu *, nghĩa đây là con trỏ kiểu void. void là 1 kiểu dữ liệu chung chung, muốn trả về kiểu gì cũng được. Phía bên trong hà m malloc ta thấy dòng size_t size, bạn hiểu nó là chứa 1 cái số để cấp phát dữ liệu. Bạn thêm 100 thì nó cấp cho 100 byte, bạn cho 1000 thì nó cấp cho 1000 byte. Số cho vào đó phải là số dương!

tôi ép kiểu (char*) để void* thành char* (vì nó trả về kiểu gì cũng được mà, con trỏ là ok).

Phía trong tôi không cho 100 hay 1000 đâu nha, cho lung tung tạch bộ nhớ máy tính thì chết. Tôi tính kích thước của ông char xem bao nhiêu bằng hàm sizeof(char). Hàm sizeof này trả về đúng kích thước của kiểu, tính theo byte. Ví dụ trong hệ 32 bit thì kiểu int là 2byte, còn trong hệ 64bit là 4byte. Chẳng hạn như thế. Mỗi máy 1 thể loại nên tôi không cho số được mà tôi nhờ máy tính tính hộ cho tôi. Sau đó tôi nhân với 10 để tạo ra 10 ô nhớ liên tiếp. Tổng hợp lại là sizeof(char) * 10

Tiếp theo câu lệnh:

free(pMangChu);

Cái này là giải phóng con trỏ này, chương trình sẽ thu hồi 10 ô nhớ mà bạn vừa cấp phát ở trên. Từ sau lệnh này pMangChu coi như là đã chết :)) Bạn mà dùng lại nó thì sinh ra lỗi ngay. Không tin cứ thử gán *pMangChu = ‘a’ xem 😀

Bạn nhớ vào đầu cho tôi, nói hơi bẩn tí là bạn ăn vào thì bạn phải ỉa ra, bạn nợ tiền ai thì bạn phải trả, đấy là quy luật ở cuộc sống rồi, có vay có trả. Bạn có vay bộ nhớ thì bạn phải trả cho nó. Bạn mà không trả thì chương trình sẽ sinh ra lỗi trong quá trình chạy như thiếu bộ nhớ, hay còn gọi là leak of memory. Cho nên cứ khắc vào đầu cứ malloc thì free. Cứ viết ra như thế cho đỡ quên. Ở các ngôn ngữ khác nó tự xử lý, cho nên năng suất chương trình không bằng C la điều đương nhiên rồi. Bạn chơi với con trỏ, bạn có quyền năng cao hơn java hay C#.

Bây giờ bạn muốn gán giá trị cho từng phần tử thì làm thế nào. Có 2 cách:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Bạn xem dòng 12 tới dòng 13. Tôi gán bình thường như bạn dùng mảng đã nói ở trên. Sau đó tôi in ra ký tự vị trí số 0(đầu tiên) đó.

Dòng 15 tới 16: Bạn nhớ cho tôi 1 điều, để lấy địa chỉ của 1 biến con trỏ, bạn cứ để nguyên tên pMangChu thì nó là địa chỉ. Muốn xem giá trị nằm trên địa chỉ này thì thêm * phía trước. Tôi dùng *(pMangChu) hay *(pMangChu + 0) là phần tử đầu tiên, *(pMangChu + 9) là phần tử thứ 10. Do vậy phép gán dòng 15 cũng tương tự với dòng 12.

Nhớ vào đầu cho tôi:

Dùng * để truy cập giá trị và để nguyên tên của biến con trỏ để truy cập địa chỉ!

Nhớ vào đầu cho tôi nhé các bạn trẻ =))

Bây giờ C nó cung cấp cho 1 thể loại không cần cấp phát bao nhiêu ô nhớ mà nó tự tính. Cụ thể như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Kết quả chạy chương trình:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Quay lại xem code. Dòng thứ 9 bạn thấy rõ ràng C cho phép gán biến con trỏ luôn cho 1 xâu. Ở đây xâu này là mảng gồm các phần tử sau:

A, n, h, dấu cách, n, h, o, dấu cách, e, m, \0 (dấu kết thúc dòng)

Vậy tôi đếm bằng tay thì có 10 phần tử nhìn thấy được, tôi for từ 0 tới 9 để in ra, đó là câu lệnh 10. Cuối chương trình tôi free nó ra :)) Có vậy thôi.

Bạn thấy C ngon chưa. Ngon đúng không? Vậy chén tiếp thôi.

Rồi, nói mãi mãi vẫn chưa tới thủ tục:

void inramanhinh(char*caicaninra)

Bây giờ nhìn thủ tục trên bạn không sợ con trỏ caicaninra nữa rồi. Nó gọi là parameter, là tham số truyền vào thủ tục để làm gì đó, như cái miệng bạn há ra để dốc cơm vào, vào ruột thì nó xử lý thế nào kệ ruột nà.

Tôi viết hàm như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Kết quả như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Đáng yêu chưa =))

Rồi tôi giải thích. Bạn viết thủ tục inramanhinh và bạn phải đặt trước main, thì ông main ông ấy mới hiểu là trên đời này còn có 1 ông sinh ra trước, ông ấy mới cho phép dùng bên trong thân hàm ông ấy được. Có cách như này cũng được nè:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

tiền trảm hậu tấu, khai báo trước,  định nghĩa sau :))

Để hiểu thủ tục tôi viết, bạn quay về với hàm printf nguyên thủy của C:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 2)

Hàm này nhận vào 1 con trỏ kiểu char và kèm các tham số phía sau. Ở đây tôi cũng dùng con trỏ là 1 char* caicaninra nên khi tôi dùng câu lệnh 15 thì nó OK đúng chuẩn ISO rồi nhá 😀

Tôi muốn các bạn muốn học C cho bài bản thì đọc kỹ hướng dẫn các hàm này ở google. Bạn có thể xem ở đây chẳng hạn.

Vậy là bạn đã biết cách viết 1 thủ tục làm việc cho bạn rồi đúng không 😀 Bạn thấy tốt cả chứ?

Bài tập cho các bạn:

  1. Hãy viết 1 hàm in ra tên bạn.
  2. Viết 1 hàm tráo đổi 2 số

Bạn nào mà coi trọng bài học này thì làm bài tập rồi comment ở dưới cho tôi code của các bạn nha.

Bài tiếp theo tôi sẽ hướng dẫn các bạn dùng makefile để build nhiều file chứ không  1 file như mấy bài đã học. Sẽ vui lắm đó. Toàn kiến thức cơ bản không :))

Happy

Bài viết gốc được đăng tải tại quynhlaptrinhc.wordpress.com

Có thể bạn quan tâm:

Tại sao phải giữ chân nhân viên?

giữ chân nhân viên
giữ chân nhân viên

Nhân viên được xem là nguồn nhân lực – “khối tài sản” quan trọng nhất của các tổ chức. Những sự kết nối tạo ra giá trị cho các doanh nghiệp bắt nguồn từ hiệu quả quản lý nguồn nhân lực. Từ đó, một vấn đề được đặt ra là liệu giữ chân nhân viên có thật sự quan trọng hay không? Và tại sao cần phải thực hiện điều đó? Cùng TopDev tìm hiểu thông qua bài viết sau.

Yếu tố con người chi phối, quyết định khả năng vận hành doanh nghiệp

giữ chân nhân viên

Có quá nhiều chiến lược nhằm đánh giá khả năng vận hành doanh nghiệp. Đồng thời cũng có rất nhiều yếu tố chi phối đến sự thành công của tổ chức. Chúng ta có thể kể đến như:

  • Xây dựng chiến lược Marketing hiệu quả;
  • Phát triển thương hiệu thông qua các sản phẩm được cải tiến về chất lượng;
  • Các dịch vụ hỗ trợ tuyệt vời;

Nếu là một freelancer it đang muốn tìm kiếm công việc, bạn có thể bị thu hút bởi những yếu tố trên trong quy trình tổ chức nhân sự.

Tuy nhiên, dường như mọi người đã quên đi một nhân tố quan trọng – nhân tố con người. 

Xem thêm: Phân tích con người – Chiến lược quan trọng trong ngành Nhân sự

Con người nhân sự là nhân tố rất quan trọng. Họ sẽ là người trực tiếp trải nghiệm và đưa ra những đánh giá khách quan nhất. Chính con người nhân sự cũng là các cá nhân lên kế hoạch phát triển chiến lược cho doanh nghiệp một cách hiệu quả nhất. Do chủ động tìm hiểu về thị trường, họ luôn nắm bắt nhanh chóng mọi thứ. Đó là lý do họ luôn thấu hiểu sự thay đổi về nhu cầu thị trường. Từ đó, dễ dàng hơn trong việc thiết lập một quy trình hoàn hảo. Đồng thời, đảm bảo mọi thứ được vận hành một cách tối ưu. 

Mặc dù việc tự động hóa, sử dụng các hệ thống điều khiển giúp giảm thiểu sự can thiệp của con người, rất hữu ích trong nhiều trường hợp, nhưng nó cũng không thể thay thế các tương tác của con người. 

Tính cạnh tranh luôn tồn tại, giữ chân nhân viên là điều tất yếu phải thực hiện

Sự cạnh tranh nhân viên diễn ra ở mọi quy mô doanh nghiệp. Nếu bạn vuột mất những cơ hội giữ chân nhân viên, họ có thể rơi vào những bến đỗ mới từ các công ty đối thủ. Các freelancer it dù không phải là official nhưng trong công tác tuyển freelancer it, công ty vẫn phải có chiến lược thiếp lập và xây dưng độ uy tín thông qua việc đồng hành và giữ chân. Giữ chân nhân viên rất không dễ dàng như bạn tưởng. Nó giống như bạn đang cố bảo vệ những bí mật thương mại của doanh nghiệp. Chúng là tài sản và cần được bảo vệ.

giữ chân nhân viên

Tuy nhiên, các nhà quản lý nhân sự cũng phải thật tỉnh táo trong các quyết định. Chỉ những nhân viên có tiềm năng phát triển mới có cơ hội được tạo điều kiện đồng hành. Nếu có nguồn nhân lực chất lượng, tố chất phù hợp thì đó là một lợi thế to lớn cho doanh nghiệp.

Tính cạnh tranh luôn tồn tại và nó dường như càng khốc liệt hơn khi thời đại ngày một phát triển hơn, con người cũng chuyên nghiệp hơn. Đặc biệt, trong thời đại số, tính cạnh tranh trên thị trường lao động rất mạnh mẽ. Nếu các nhà quản lý không thể giải quyết được bài toán về việc giữ chân nhân viên, đó sẽ là một sự thụt lùi đáng kể.

Câu chuyện nắm bắt được thị trường và tính cạnh tranh là điều cần quan tâm. Song, các nhà quản lý nhân sự cũng cần có những giải pháp thực tế. Điều này giúp tạo ra lợi thế khai mở tiềm năng thu hút nhân sự, góp phần xây dựng một lực lượng nhân viên vững mạnh.

Nhân viên cũng có “giá”

Liệu  có thể tính được giá trị cụ thể của một nhân viên dưới góc độ tài chính hay không? Đáp án là có và tất nhiên có. 

Hãy thử đặt ra câu hỏi và giải đáp nó bằng những hình dung.

Mất đi một sự đồng hành, doanh nghiệp sẽ mất đi những gì?

giữ chân nhân viên

  • Chi phí về tuyển dụng quảng cáo, freelancer it, phỏng vấn và sàng lọc một ứng viên mới.
  • Tiếp đến chính là chi phí để thiết lập lộ trình đào tạo một người mới: đào tạo và quản lý.
  • Năng suất có sự tác động khi một nhân viên mới sẽ mất từ 1-2 năm để đạt được hiệu suất làm việc như nhân tài cũ.
  • Các chi phí xử lý cho các rủi ro nhỏ có thể xảy ra trở nên nhiều hơn. Do đang thích nghi, họ khó nắm bắt kịp các vấn đề trọng tâm trong công việc.
  • Tạo ra sự tác động đến môi trường làm việc: Một ai đó rời đi, nhiều suy nghĩ sẽ được đặt ra. Điều này tạo ra sự nghi ngờ, tâm lý hoang mang xung quanh môi trường làm việc. 

Chi phí để thay thế một nhân viên là bao nhiêu?

Theo một nghiên cứu của CAP, chi phí trung bình để thay thế một nhân viên được diễn đạt như sau:

– 16% tiền lương hàng năm cho các công việc lương thấp (dưới 30.000 đô la/năm).

Ví dụ: chi phí để thay thế một nhân viên bán lẻ  10$/ giờ sẽ là 3,328$. 

– 20% tiền lương hàng năm cho các vị trí tầm trung (30.000 đến 50.000 đô/năm).

Ví dụ: chi phí để thay thế người quản lý $40.000 sẽ là $8.000.

– 213% tiền lương hàng năm cho các vị trí điều hành có trình độ học vấn cao.

Ví dụ: chi phí để thay thế một CEO 100 nghìn đô la là 213.000 đô la.

Lời kết

Mọi nhân viên đều có một vị trí, một cái “giá” riêng. Và việc bạn đánh mất đi một hay nhiều nhân viên tài năng là một sự thiệt thòi lớn. Giữ chân nhân viên là một việc hết sức quan trọng và cần được đầu tư đúng mức. Một doanh nghiệp có phát triển lâu dài được hay không là dựa vào một đội ngũ nhân viên chất lượng. Vì thế, hãy lập các kế hoạch giữ chân nhân viên của bạn nhé. Tất nhiên, kế hoạch đó chỉ dành cho những nhân viên thật sự xứng đáng với các giá trị mà họ đang sở hữu.


Tuyển Dụng Nhân Tài IT Cùng TopDev
Đăng ký nhận ưu đãi & tư vấn về các giải pháp Tuyển dụng IT & Xây dựng Thương hiệu tuyển dụng ngay!
Hotline: 028.6273.3496 – Email: contact@topdev.vn
Dịch vụ: https://topdev.vn/page/products

Có thể bạn quan tâm:

Xem thêm Top Việc làm Developer trên TopDev

Sứ mệnh và thách thức cho các “anh hùng” công nghệ tại Viettel Cyber Security

Chính thức thành lập từ tháng 4 năm 2019, Viettel Cyber Security (Trung tâm An ninh mạng Viettel) đã không ngừng thể hiện sức mạnh, khẳng định vị thế đứng đầu trong việc đảm bảo an ninh trên không gian mạng Việt Nam. 

Khẳng định vị thế hàng đầu – Sức mạnh “niềm tin” lan tỏa

Khởi đầu với 6 nhân sự từ năm 2011, Công ty An ninh mạng Viettel đã phát triển thành một đơn vị lớn mạnh với hơn 200 nhân sự và chính thức trở thành công ty riêng biệt sau 8 năm với tên gọi Viettel Cyber Security.

Là đơn vị trực thuộc Tập đoàn Công nghiệp Viễn thông Quân đội, Viettel Cyber Security có vai trò quan trọng trong việc thực hiện các nghiên cứu chuyên sâu, phát triển giải pháp đảm bảo An toàn thông tin các hệ thống của Tập đoàn cũng như cung cấp những sản phẩm, dịch vụ chất lượng đến với khách hàng trong nước và quốc tế.

Trải qua nhiều năm vươn lên phát triển, Viettel Cyber Security đã chiếm được sự tín nhiệm của các đối tác về chất lượng và đó cũng chính là lời cam kết mà Viettel Cyber Security dành cho các khách hàng của công ty.

Được mệnh danh là “tấm lá chắn thép khổng lồ” của doanh nghiệp Việt trước những mối nguy hiểm trên không gian mạng, Viettel Cyber Security đã đem đến một sự tin tưởng gần như tuyệt đối với những con số ấn tượng:

  • Hàng chục nghìn máy chủ, thiết bị mạng và hàng triệu đường truyền, thuê bao di động được bảo vệ an toàn nhờ sự nghiên cứu, xây dựng hệ thống giám sát, phòng thủ toàn diện.
  • Hơn 25.000 cuộc tấn công an ninh mạng từ các hacker trên thế giới nhắm vào Viettel và các khách hàng mỗi năm được phát hiện và ngăn chặn mỗi năm.
  • Hơn 100 lỗ hổng bảo mật zero-day được tìm thấy bởi các chuyên gia an toàn thông tin Viettel Cyber Security.

Những con số này không chỉ thể hiện sự đảm bảo về an toàn thông tin, mà còn cho thấy sự đầu tư của Viettel Cyber Security về chất lượng của đội ngũ nhân sự – Một trong những yếu tố then chốt tạo nên tầm vóc của công ty. 

Đội ngũ nhân sự chất lượng – Niềm tự hào của Viettel Cyber Security

Cho đến nay đội ngũ chuyên gia an toàn thông tin tại Viettel Cyber Security vẫn không ngừng tìm tòi, trau dồi kinh nghiệm để cải thiện chất lượng các dịch vụ, giải pháp của công ty. Mọi cố gắng đã được công nhận bởi những danh hiệu danh giá, những giải thưởng ấn tượng giúp thương hiệu Viettel vươn tầm quốc tế:

  • Giải đồng IT World Awards 2017; 
  • Giải bạc Stevie Awards 2017; 
  • Giải thưởng cho “Sản phẩm an toàn thông tin chất lượng cao” được công nhận bởi VNISA;
  • Giải “Dịch vụ an toàn thông tin tiêu biểu”, “Sản phẩm An toàn thông tin mới xuất sắc” do VNISA trao tặng;
  • Đạt “Danh hiệu sao khuê 2020” do VINASA công nhận; 
  • Danh hiệu “Chìa khóa vàng” 2020 với 9 giải thưởng được trao cho các sản phẩm, dịch vụ an toàn thông tin;
  • Danh hiệu “Nhà cung cấp dịch vụ quản lý an ninh mạng tốt nhất Việt Nam – Vietnam Managed Security Service Provider of the Year” năm 2020 của giải thưởng Frost & Sullivan trong khu vực châu Á – Thái Bình Dương.

Với những thành tích và sản phẩm, dịch vụ xuất sắc của mình, Viettel Cyber Security xứng đáng là “Tấm lá chắn thép khổng lồ” của các doanh nghiệp Việt trước những rủi ro và thách thức trên không gian mạng, tạo sự tin tưởng của khách hàng và đối tác dành cho công ty.

Bí mật phía sau những thành tựu của Viettel Cyber Security

Không chỉ mang đến sự tin tưởng tuyệt đối cho đối tác và khách hàng, niềm tin còn được công ty gửi trao đến toàn bộ những con người đã đóng góp sức lực và trí tuệ để xây dựng thương hiệu Viettel Cyber Security như hôm nay.

Coi trọng giá trị con người, cũng vì thế mà mỗi thành viên trong tổ chức luôn được quan tâm bằng những chính sách đãi ngộ xứng đáng giúp thúc đẩy động lực làm việc đồng thời lan tỏa niềm đam mê.

Cùng khám phá ngay những điều tuyệt vời đang chờ đợi các tài năng công nghệ:

  • Mức thu nhập hấp dẫn và xứng đáng;
  • Các CLB giải trí đầy hấp dẫn: CLB bóng đá, bóng bàn, bi-a, vẽ tranh, e-sport, chạy bộ, đạp xe,…
  • Có thêm chế độ bảo hiểm tại Bệnh viện TW Quân đội 108 và chế độ tại khu khám chữa bệnh chuyên biệt dành riêng cho CBCNV Viettel và người thân;
  • Có cơ hội làm việc với các chuyên gia hàng đầu, kinh nghiệm lâu năm trong ngành ATTT (top 100 hacker Facebook, Microsoft,…);
  • Có cơ hội tham gia các hội thảo ATTT trong nước và thế giới (Singapore, Mỹ, Tây Ban Nha,…);
  • Tham gia môi trường làm việc trẻ trung, hiện đại, nhiều cơ hội phát triển sự nghiệp;
  • Các hoạt động ngoại khóa, thể thao, văn hóa giúp xả hơi sau những giờ làm việc vất vả;
  • Thời gian làm việc linh động, trang phục thoải mái cùng các sự kiện teambuilding hàng quý, 12 ngày nghỉ phép trong năm và 3 ngày nghỉ dưỡng với mức hỗ trợ 9 triệu/người.

Để đáp ứng nhu cầu mở rộng và phát triển của mình, công ty kỳ vọng đến năm 2021, quy mô lực lượng nhân sự An toàn Thông tin của Viettel Cyber Security sẽ lên đến con số 500 người.

Đặc biệt, Viettel Cyber Security hiện đang vẫy gọi các tài năng công nghệ gia nhập và “chinh chiến” với vị trí Test Engineer

Nếu bạn yêu thích lĩnh vực công nghệ và mong muốn trở thành một trong những “người hùng” đóng góp sức mình bảo vệ an toàn thông tin cho hàng triệu người dùng Việt Nam thì Viettel Cyber Security chính là sự lựa chọn tuyệt vời.

>>> Vậy bạn còn chần chờ chi không mau nhấn nút APPLY và kích hoạt cho sự nghiệp mới ngay hôm nay.

>>> Đồng hành cùng Viettel Cyber Security viết nên câu chuyện sự nghiệp mới đầy rực rỡ!

Tái cấu trúc mã nguồn

Tái cấu trúc mã nguồn

Bài viết được sự cho phép của BBT Tạp chí Lập trình

Khái niệm

Mỗi người có một khái niệm tái cấu trúc mã nguồn (code refactoring) khác nhau, và khi chuyển ngữ sang tiếng việt, thì việc tìm một thuật ngữ chính xác càng khó hơn. Ở đây tôi xin chuyển nghĩa từ refactoring thành tái cấu trúc và chọn định nghĩa của Martin Fowler:

Tái câu trúc là thay đổi ở cấu trúc bên trong mà không làm thay đổi hành vi với bên ngoài của hệ thống.

Tái cấu trúc là một quá trình cơ học, hình thức và trong nhiều trường hợp rất đơn giản để làm việc với mã của hệ thống đã tồn tại để chúng trở nên “tốt hơn”. Khái niệm “tốt hơn” là một khái niệm mang tính chủ quan, và không có nghĩa là luôn làm ứng dụng chạy nhanh hơn mà thường được hiểu là theo các kỹ thuật hướng đối tượng, tăng an toàn kiểu dữ liệu, cải thiện hiệu xuất , đễ đọc, dễ bảo trì và mở rộng.

  Các kĩ sư Pinterest đã xây dựng Progressive Web App như thế nào?
  10 trang web hàng đầu để tìm hiểu WordPress

Hiệu quả của tái cấu trúc

Sản xuất phần mềm sẽ không hiệu quả nếu như bạn không thể theo kịp thay đổi của thế giới. Nếu như chúng ta chỉ sản xuất ra các phần mềm trong một vài ngày thì đơn giản hơn rất nhiều. Nhưng trong thế giới này chúng ta có rất nhiều đối thủ cạnh tranh. Nên nếu bạn không tái cấu trúc phần mềm của mình, khi đối thủ có một số tính năng hữu ích mới mà bạn không cập nhật thì sản phẩm của bạn nhanh chóng bị lạc hậu. Bởi thế là một lập trình viên bạn phải đón nhận và hành động một cách thích hợp với những thay đổi. Và khi thực hiện tái cấu trúc mã là bạn đang làm điều đó.

Cải thiện thiết kế

Nếu không áp dụng tái cấu trúc khi phát triển ứng dụng, thì thiết kế sẽ ngày càng tồi đi. Vì khi phát triển ứng dụng thì ta sẽ ưu tiên cho các mục tiêu ngắn hạn (đặc biệt khi áp dụng các quy trình phát triển linh hoạt), nên mã ngày càng mất đi cấu trúc. Một trong những tên của vấn đề này gọi là technical debt (nợ kỹ thuật). Khi xảy ra vấn đề thì rất khó để quản lý và dễ bị tổn thương .Thế nên việc áp dụng tái cấu trúc sẽ giúp cho mã giữ được thiết kế tốt hơn là ưu điểm quan trọng.

Mã dễ đọc hơn

Khi lập trình là chúng ta đang giao tiếp với máy tính để yêu cầu chúng làm điều mình muốn. Nhưng còn có người khác tham gia vào quá trình này là các lập trình viên khác hay chính chúng ta trong tương lai. Chúng ta biết khi lập trình thường sẽ có người phải đọc để kiểm tra xem có vấn đề với mã đó không hoặc để mở rộng hệ thống.

Nhưng có một vấn đề là khi làm việc, lập trình viên thường không nghĩ tới những người đó trong tương lai. Vậy thì trong trường hợp này tái cấu trúc đóng vai quan trọng là giúp cải thiện thiết kế của hệ thống, từ đó cũng giúp đọc mã dễ hơn.

Lợi ích hệ quả

Từ những lợi ích cơ bản ở trên ta có thêm các lợi ích khác: do hệ thống hiện thời có một thiết kế tốt hơn và mã dễ hiểu hơn, từ đó thì việc mở rộng hệ thống dễ dàng hơn, khó bị tổn thương hơn, nên tốc độ phát triển hệ thống luôn được duy trì; mã và thiết kế dễ đọc hơn, từ đó giúp tìm ra lỗi dễ dàng hơn; vì những mục tiêu ngắn hạn lập trình viên có thể chấp nhận một lỗ hổng nào đó về công nghệ hay thiết kế mà hiện thời không gây ảnh hưởng gì tới hệ thống, nhưng khi hệ thống lớn dần thì những lỗ hổng này được tích tụ và làm cho hệ thống dễ bị tổn thương, thể nên việc tái cấu trúc giúp nhanh chóng sửa những lỗ hổng này.

Thời điểm thực hiện

Khi thêm một chức năng mới

Khi thêm một chức năng mới, ta phải đọc lại mã để hiểu. Như vậy nếu lúc này ta thực hiện việc tái cấu trúc, mã sẽ dễ hiểu hơn, cộng với đó là này ta cũng dễ dàng hiểu mã hơn vì mình là người đã đọc và thực hiện việc tái cấu trúc. Một lý do khác là khi thực hiện việc tái cấu trúc vào thời điểm này thì thiết kế của hệ thống sẽ tốt hơn, từ đó việc mở rộng cũng dễ dàng hơn.

Khi sửa lỗi

Khi sửa lỗi ta cũng phải đọc mã, và như vậy việc tái cấu trúc làm mã dễ đọc hơn, có cấu trúc rõ ràng hơn từ đó dễ dàng phát hiện lỗi là điều cần thiết. Và bởi thế nếu bạn được gán là người sửa một lỗi nào đó thì bạn cũng thường được gán là người phải tái cấu trúc mã.

Khi rà soát mã

Nhiều tổ chức thực hiện việc rà soát mã (code review). Rà soát mã giúp cho các lập trình viên giỏi truyền lại cho các lập trình viên ít kinh nghiệm hơn, giúp cho mọi người viết mã rõ ràng hơn. Mã có thể là rất rõ ràng với tác giả, nhưng với người khác thì có thể không, bởi thế rà soát mã sẽ làm cho nhiều người đọc mã hơn. Có nhiều người đọc mã thì mã phải dễ đọc hơn và có nhiều ý tường hơn được trao đổi giữa các thành viên trong nhóm hơn. Bởi thế khi bạn thực hiện rà soát bạn phải đọc mã. Lần đầu bạn đọc bạn bắt đầu hiểu mã. Lần tiếp theo bạn sẽ có nhiều ý tưởng hơn để tái cấu trúc mã, từ đó bạn có thể thực hiện việc tái cấu trúc.

Các “mã bẩn” thường gặp

Chúng ta đã biết cần thực hiện tái cấu trúc khi nào, nhưng có một câu hỏi khác là mã như thế nào thì cần tái cấu trúc? Khái niệm mã bẩn (code smell) là mã có thể sinh vấn đề một cách lâu dài, sẽ giúp ta phát hiện mã cần phải tái cấu trúc. Sau đâu chúng ta sẽ liệt kê một số loại mã bẩn thường gặp:

  • Mã lặp

    Là những đoạn mã xuất hiện nhiều hơn một lần trong một hoặc nhiều ứng dụng của một chủ thể. Đó là hệ quả của các hành động: sao chép mã; các chức năng tương tự được viết bởi các lập trình viên khác nhau. Hệ quả là mã trở nên dài hơn, khó hiểu hơn và khó bảo trì hơn.

    Ví dụ đoạn mã tính giá trị trung bình của một mảng số nguyên trên C

    [sourcecode language=”c”] extern int array1[];
    
    extern int array2[];
    
    int sum1 = 0;
    int sum2 = 0;
    int average1 = 0;
    int average2 = 0;
    
    for (int i = 0; i < 4; i++)
    {
    sum1 += array1[i];
    }
    average1 = sum1/4;
    
    for (int i = 0; i < 4; i++)
    {
    sum2 += array2[i];
    }
    average2 = sum2/4;
    
    [/sourcecode]

    Ta thấy hai vòng lặp for là giống nhau!

  • Hàm dài

    Hàm dài là quá phức tạp, có lượng mã lớn. Nên khó để hiểu, triển khai, bảo trì và tái sử dụng. Nên việc tách thành các hàm nhỏ hơn là điều cần thiết.

  • Lớp lớn

    Lớp lớn là lớp chứa quá nhiều thuộc tính và chức năng, thường là của nhiều lớp khác. Bởi thế cúng khó để đọc, bảo trì và tái sử dụng. Nên cần thực hiện các kỹ thuật cần thiết để phân bổ thành nhiều lớp khác nhau.

  • Hàm có nhiều tham số đầu vào

    Khi một hàm có nhiều tham số đầu vào sẽ gây khó khăn để đọc, dùng và thay đổi. Với các ngôn ngữ lập trình hướng đối tượng ta có thể nhóm các tham số có liên quan vào một đối tượng để giảm số lượng tham số đầu vào.

  • Tính năng không phải của lớp

    Là hiện tượng một phương thức không nên thuộc một lớp, nhưng do phương thức muốn sử dụng các dữ liệu của lớp đó nên lập trình viên đã gán phương thức cho lớp. Đây là một vi phạm trong lập trình hướng đối tượng. Ta cần trả phương thức đó về đúng đối tượng.

  • Lớp có quan hệ quá gần gũi

    Đó là hiện tượng hai lớp có thể truy xuất vào các thuột tính riêng tư của nhau một cách không cần thiết. Điều đó đẫn đến là chính các lớp đó hay lớp con của chúng có thể thay đổi các thuộc tính của lớp con lại một cách “vô thức”.

  • Lớp quá nhỏ

    Việc tạo, bảo trì và hiểu một lớp tốn tài nguyên. Vậy nếu lớp đó quá nhỏ thì ta nên xóa bỏ lớp đó đi.

  • Lệnh switch

    Một trong những dấu hiệu tốt của lập trình hướng đối tượng là việc không dùng lệnh switch. Vấn đề của lệnh switch chủ yếu là vấn đề lặp mã. Bạn thường gặp những lệnh switch để phân bổ các chức năng ở nhiều nơi khác nhau trong cùng một ứng dụng. Và mỗi khi bạn thêm một tính năng mới, bạn phải tìm ở tất cả các lệnh này để thay đổi.

  • Từ chối kế thừa

    Điều này xảy ra khi một lớp được thừa kế dữ liệu cũng như các tính năng của lớp cha, nhưng lại không cần phải dùng tới chúng. Chúng ta không thể cấm đoán điều, nhưng nếu điều này xảy ra thường dẫn tới vấn đề hiểu lầm và vấn đề.

  • Định danh quá dài hoặc quá ngăn

    Các định danh cần mô tả đủ ý nghĩa để mã dễ đọc hơn và tránh gây hiểu nhầm. Bởi thế các định danh quá ngẵn thường không mô tả hết ý nghĩa và gây ra nhầm lẫn. Nhưng các định danh quá dài cũng có vấn đề tương tự. Bởi thế trong trường hợp này chúng ta có thể viết tắt hay tìm định danh thay thế.

  • Dùng quá nhiều giá trị

    Nếu trong mã có nhiều giá trị thì khi cần phải thay đổi các giá trị đó vì một lý do nào đó (ví dụ thay đổi độ chính xác) thì bạn cần phải thay đổi ở nhiều nơi. Không chỉ thế mà không phải ai và lúc nào cũng nhớ những giá trị đó có ý nghĩa gì, nên làm cho mã trở nên khó đọc hơn. Trong trường hợp này bạn có thể thay bằng cách đặt tên cho các hằng.

    Các kỹ thuật tái cấu trúc cơ bản

    Các kỹ thuật tái cấu trúc được chia thành các nhóm tùy theo tiêu chí. Ở đây chúng ta sẽ chia theo mục đích.

    Trừu tượng hóa

    Chia nhỏ mã

    Chuẩn hóa mã

Kết luận

Cải tiển là công việc cần thiết và đem lại hiệu quả cao. Nhưng lượng các kỹ thuật mà ta áp dụng được cho dự án của mình thì rất nhiều và tốn kém thời gian. Trong bài viết này tôi không hy vọng sẽ trình bày được tất cả hay nhiều kỹ thuật mà chỉ là một số kỹ thuật căn bản nhất.

Tài liệu tham chiếu

Fowler, M., K. Beck, et al. (1999). Refactoring: Improving the Design of Existing Code.

Ritchie, P. “Refactoring with Microsoft Visual Studio 2010.”

(2011). from http://sourcemaking.com/refactoring.

Nguồn hanoiscrum.net

Bài viết gốc được đăng tải tại tapchilaptrinh.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Cơ bản về Class trong C++

Cơ bản về Class trong C++

Bài viết được sự cho phép của tác giả Khiêm Lê

Class là gì?

Class hay lớp là một mô tả trừu tượng (abstract) của nhóm các đối tượng (object) có cùng bản chất, ngược lại mỗi một đối tượng là một thể hiện cụ thể (instance) cho những mô tả trừu tượng đó. Một class trong C++ sẽ có các đặc điểm sau:

  • Một class bao gồm các thành phần dữ liệu (thuộc tính hay property) và các phương thức (hàm thành phần hay method).
  • Class thực chất là một kiểu dữ liệu do người lập trình định nghĩa.
  • Trong C++, từ khóa class sẽ chỉ điểm bắt đầu của một class sẽ được cài đặt.
  Factory Function vs. Class
  Các kiểu dữ liệu trong lập trình C/C++ (Data type)

Ví dụ về một class đơn giản, class Car. Một chiếc xe hơi vậy thì sẽ có chung những đặc điểm là đều có vô lăng, có bánh xe nhiều hơn 3, có động cơ… Đó là một class, một cái model hay mẫu mà người ta đã quy định là nếu đúng như vậy thì nó là xe hơi. Nhưng mà xe thì có thể có nhiều hãng khác nhau, BMW, Vinfast, Toyota… Thì mỗi hãng xe lại có những model xe khác nhau nhưng chúng đều là xe hơi. Vậy thì trong lập trình cũng vậy, class là quy định ra một mẫu, một cái model mà các thể hiện của nó (instance) hay đối tượng (object) phải tuân theo.

Khai báo class và sử dụng class

Cú pháp khai báo một class cơ bản trong C++ như sau:

class <ClassName> {
    <access_modifier>:
        <data_type> property;

        <return_type> <method_name>(arguments) {
            return <something_match_return_type>;
        }

        <_return_type> <_method_name>(_arguments);
};

<_return_type> <ClassName>::<_method_name>(_arguments) {
    return <something_match_return_type>;
}

Ví dụ một class cơ bản:

class Person {
    public:
        string firstName; // property
        string lastName;  // property
        int age;          // property

        void fullname() { // method
            cout << firstName << ' ' << lastName;
        }
};

Trở lại với ví dụ ở đầu bài viết, class ở đây là Car, vậy thì thuộc tính của nó chính là speed, HP,… còn phương thức chính là run, turn left, right, turn on the light…

Lưu ý: các thuộc tính có thể bị trùng tên với các tham số trong các phương thức, vậy nên chúng ta nên dùng this-> hoặc toán tử phân giải phạm vi (::), ví dụ:

class Person {
    public:
        string firstName;
        string lastName;
        int age;

        void fullname() {
            cout << this->firstName << ' ' << Person::lastName;
        }
};

Nói qua một chút về con trỏ this, con trỏ this đề cập đến thể hiện hay instance của class đó. Do đó, thông qua con trỏ this, ta có thể truy cập đến các thuộc tính hoặc phương thức thuộc class đó như trên ví dụ bên trên.

Đối với toán tử phạm vi :: dùng để xác định phương thức hoặc thuộc tính được gọi thuộc lớp nào. Như trong ví dụ trên là truy xuất thuộc tính lastName thuộc lớp Person. Nếu như gọi từ namespace hoặc emum thì toán tử :: được dùng để gọi thành viên của namepsace hoặc enum đó. Ngoài ra, toán tử phân giải phạm vi nếu không có tên lớp phía trước thì được dùng để gọi một biến bên ngoài scope. Ví dụ:

int x;
int main()
{
    int x = 2;
    ::x = 3; // x ở ngoài
    return 0;
}

Sự khác biệt giữa this và class khá rõ ràng, this (ám chỉ thể hiện của class đang sử dụng this) chỉ sử dụng được trong class, còn đối với toán tử :: có thể sử dụng được cả ở trong và ngoài class. Quá rõ ràng, nếu dùng this ở ngoài thì biết nó chỉ thằng nào đúng không! Bạn không thể thay ::x ở ví dụ trên thành this->x hay ->x được.

Cú pháp tạo object của một class và sử dụng các thuộc tính và phương thức:

// tạo một object
<className> <object>;
// gán giá trị cho thuộc tính của object
<object>.property = <value>;

// có thể sử dụng property như một biến thông thường
cout << <object>.property;
// có thể sử dụng method như một hàm thông thường
<object>.method();

Lưu ý: chỉ những thuộc tính và phương thức public thì mới có thể được sử dụng như cách trên. Ví dụ về cách sử dụng class:

Person person;
person.firstName = "Khiem";
person.lastName = "Le";
person.fullname(); // sẽ in ra màn hình là "Khiem Le"

Access modifiers & properties declaration

Access modifier là phạm vi truy cập của các thuộc tính và phương thức sẽ được khai báo bên dưới nó. Có 3 phạm vi truy cập trong C++ là public, private và protected.

  • Các thuộc tính và phương thức khai báo public thì có thể được truy cập trực tiếp thông qua instance của class đó. Các thuộc tính nên khai báo là public nếu bạn không có ràng buộc điều kiện trước khi gán (người dùng có thể thoải mái gán giá trị) hoặc bạn không cần xử lý trước khi trả về giá trị thuộc tính;
  • Đối với private thì chỉ có thể được truy cập gián tiếp qua các phương thức public (Getter và setter). Các thuộc tính private thường được sử dụng khi bạn không mong muốn người khác có thể tùy ý gán giá trị hoặc là bạn muốn xử lý trước khi trả về giá trị.
  • Đối với protected, các phương thức và thuộc tính chỉ có thể truy cập qua các class kế thừa nó hoặc chính nó (sẽ được nói kĩ hơn trong bài kế thừa C++).

Ví dụ của access modifier:

class MyClass
{
	public:
		int public_property;

	private:
		int _private_property;

	// protected sẽ được trình bày trong bài kế thừa và đa hình trong C++
};

Đối với quy cách đặt tên biến, bạn có thể sử dụng PascalCase, CammelCase… nhưng đối với các thuộc tính và phương thức private bạn nên đặt tên có dấu _ đầu. Ví dụ như _privateProp. Trong một số ngôn ngữ bật cao, thậm chí đã không còn từ khóa private mà thay vào đó sẽ chỉ là dấu _ trước tên biến (ví dụ như Dart).

Method declaration

Phương thức cũng giống như một hàm bình thường, bạn cũng có thể không trả về giá trị, có thể có hoặc không có tham số, có thể override hàm… Đối với các tham số truyền vào phương thức, bạn cũng có thể đặt tên trùng với thuộc tính của class, sử dụng kết hợp với toán tử :: và con trỏ this. Hoặc bạn có thể đặt tên khác với thuộc tính (thường thì sẽ thêm dấu _ trước tên tham số như là thuộc tính private vậy).

Đối với phương thức thì có hai cách định nghĩa thi hành: định nghĩa thi hành trong lúc định nghĩa class và định nghĩa thi hành bên ngoài class.

Định nghĩa thi hành bên trong class:

class Animal {
    public:
        string sound;

        void makeNoise() {
            cout << sound;
        }
};

Định nghĩa thi hành bên ngoài class:

class Animal {
    public:
        string sound;

        void makeNoise();
};

void Animal::makeNoise() {
    cout << sound;
}

Lưu ý: các phương thức không làm thay đổi giá trị thuộc tính của đối tượng thì nên có từ khóa “const” trước phần thân. Ví dụ:

class Animal {
    public:
        string sound;

        void makeNoise() const;
};

void Animal::makeNoise() const {
    cout << sound;
}

Getter & setter

Đối với thuộc tính private, ta không thể truy cập trực tiếp từ bên ngoài, vậy có cách nào để truy cập? Đây là lúc sử dụng phương thức. Các phương thức lấy giá trị của thuộc tính được gọi là getter, các phương thức gán giá trị cho thuộc tính được gọi là setter.

class MyClass {
    private:
        int _age;

    public:
        int getAge() {         // getter
            return _age;
        }

        void setAge(int age) { // setter
            _age = age;
        }
};

Việc sử dụng các thuộc tính private nhằm mục đích không cho người khác tùy ý thay đổi giá trị của thuộc tính đó, ngoài ra còn giúp bạn xử lý kết quả trước khi trả về cho người yêu cầu. Việc đó được thực hiện thông qua getter và setter. Ví dụ:

class MyClass {
    private:
        int _age;

    public:
        bool isOldEnough() {
            if (_age >= 18)
                return 1;
            return 0;
        }

        int getAge() {
            return _age;
        }

        void setAge(int age) {
            if (age < 18) {
                cout << "You are not old enough\n";
            } else {
                _age = age;
            }
        }
};

Lưu ý cách đặt tên getter và setter. Bạn nên đặt get vào trước tên getter và set vào trước tên setter như ví dụ bên trên của mình. Và cũng theo như phần lưu ý cuối mục “Method declaration” ở trên, các getter nên đặt là “const” bởi vì getter chỉ lấy giá trị chứ không thay đổi giá trị thuộc tính.

Constructor

Constructor hay hàm dựng là một hàm đặc biệt, nó sẽ được gọi ngay khi chúng ta khởi tạo một object. Vậy thì tại sao chúng ta lại cần có constructor?

Nếu bạn để ý ví dụ trên bạn sẽ thấy ta phải khởi tạo một object sau đó gán các property và sử dụng, việc này rất tốn thời gian. Constructor sẽ giúp chúng ta giải quyết việc này. Cú pháp khai báo một constructor giống với hàm nhưng không có kiểu dữ liệu trả về:

class MyClass {
  public:
    MyClass() { // constructor
      cout << "Hello World!";
    }
};

// sử dụng
MyClass object; // sẽ in ra màn hình "Hello World"

Lưu ý constructor phải được khai báo public. Công dụng chính của constructor chính là khởi gán các thuộc tính, vậy nên constructor thường được định nghĩa như sau:

class Person {
	public:
	    string firstName;
	    string lastName;
	    int age;

	    Person(string _firstName, string _lastName, int _age)
	    {
	        firstName = _firstName;
	        lastName = _lastName;
	        age = _age;
	    }

	    void fullname() {
			cout << firstName << ' ' << lastName;
	    }
};

Constructor cũng có thể định nghĩa thi hành bên ngoài class giống như phương thức vậy:

class Person {
	public:
	    string firstName;
	    string lastName;
	    int age;

	    Person(string _firstName, string _lastName, int _age);

	    void fullname() {
	        cout << firstName << ' ' << lastName;
	    }
};

Person::Person(string _firstName, string _lastName, int _age)
{
	firstName = _firstName;
	lastName = _lastName;
	age = _age;
}

Để khởi tạo một object thông qua constructor, ta làm như sau:

Person person("Khiem", "Le", 20);
person.fullname(); // Khiem Le

Như vậy chúng ta không cần phải set từng thuộc tính cho object đó mà khởi tạo trực tiếp qua constructor.

Destructor

Đối với một số ngôn ngữ lập trình khác có thể destructor không phổ biến, nhưng đối với C++, việc được quản lý bộ nhớ một cách hoàn toàn do người lập trình làm chủ thì destructor là vô cùng cần thiết. Hãy thử nghĩ xem, trong số thuộc tính của class bạn định nghĩa có một con trỏ, mảng động… và bạn không sử dụng desctructor thì sẽ như thế nào? Đương nhiên sẽ xảy ra chuyện rò rỉ bộ nhớ và điều này cực kì không tốt. Với destructor bạn có thể xóa con trỏ đi khi object được thu hồi hoặc bạn có thể gọi tường minh destructor.

Cách khai báo destructor cũng giống như đối với constructor nhưng có kí hiệu ~ phía trước:

class MyClass {
    public:
        MyClass() { // constructor
            cout << "Constructor is executed\n";
        }

        ~MyClass() { // destructor
            cout << "Constructor is executed\n";
        }
};

// Khởi tạo object
ClassName t; // gọi constructor không tường minh
// Gọi destructor tường minh
t.~MyClass();

Static member

Static member hay thành viên tĩnh trong class C++ cũng tương tự như với static variable (biến tĩnh) trong function. Đối với function, sau khi thực hiện xong khối lệnh và thoát thì biến tĩnh vẫn sẽ không mất đi. Đối với class, thành viên tĩnh sẽ là thuộc tính dùng chung cho tất cả các đối tượng của class đó, cho dù là không có đối tượng nào tồn tại. Tức là bạn có thể khai báo nhiều object, mỗi object các thuộc tính của nó đều khác nhau nhưng riêng static thì chỉ có một và static member tồn tại trong suốt chương trình cho dù có hay không có object nào của nó hay nói ngắn gọn là dùng chung một biến static.

Các thành viên tĩnh của class có thể được truy cập từ bất kì đối tượng nào của class đó hoặc thông qua toán tử phạm vi (::). Biến tĩnh cũng có phạm vi truy cập như một biến thông thường (public, private và protected). Để khai báo một biến tĩnh, ta thực hiện thêm từ khóa “static” vào trước kiểu dữ liệu, sau đó khởi tạo giá trị bên ngoài như sau:

class MyClass {
    public:
        static int count;
};

int MyClass::count = 0;

Bây giờ bạn có thể sử dụng biến tĩnh như cách đã trình bày bên trên:

cout << MyClass::count; // 0
MyClass::count++; // 1

Để thấy được sự “dùng chung” của static member, các bạn có thể xem ví dụ sau:

MyClass khiemle;
khiemle.count = 100;
cout << MyClass::count; // 100

Trong ví dụ trên rõ ràng là mình chỉ set thuộc tính của object khiemle thôi nhưng mà khi in biến count qua toán tử phạm vi thì vẫn được kết quả là 100. Nghĩa là tất cả các object đều dùng chung thuộc tính static đó. Bạn có thể đặt thuộc tính tĩnh là hằng như sau:

class MyClass {
    public:
        static const int count;
};

const int MyClass::count = 0;

Thuộc tính là const sẽ không được thay đổi trong suốt chương trình, do đó bạn có thể gán giá trị ngay khi khai báo như sau:

class MyClass {
    public:
        static const int count = 0;
};

//const int MyClass::count = 0; Không cần dòng này nữa

Lưu ý là đối với static member không phải là hằng bạn sẽ không gán giá trị như cách trên được:

class MyClass {
    public:
        static int count = 0; // không được phép
};

Tiếp theo là phương thức tĩnh. Phương thức tĩnh cũng giống như thuộc tính tĩnh, chúng ta có thể gọi trực tiếp qua toán tử phạm vi mà không cần một object nào của nó tồn tại cả.

class MyClass {
	public:
	    static void sayHello() {
	        cout << "Hello";
	    }
};

MyClass::sayHello(); // Hello

Lưu ý là các phương thức tĩnh sẽ chỉ truy cập được đến các biến tĩnh và phương thức tĩnh khác chứ không được truy cập thành viên khác ngoài static member.

class Person {
	public:
	    string firstName;
	    string lastName;

	    static void fullname() {
	        cout << firstName << ' ' << lastName; // không hợp lệ
	    }
};

Tổng kết

Qua bài viết này, mình đã giới thiệu cho các bạn về class, thuộc tính, phương thức và hàm dựng trong C++. Trong bài viết thì cách đặt tên hàm, biến có phần không thống nhất với nhau, bạn nên chọn một cách đặt tên phù hợp nhất với bản thân để clean code. Nếu có sai xót hoặc thắc mắc gì, các bạn có thể để lại bình luận bên dưới bài viết để giúp mình phát triển bài viết tốt hơn. Cảm ơn các bạn đã theo dõi bài viết!

Bài viết gốc được đăng tải tại khiemle.dev

Có thể bạn quan tâm:

Xem thêm Việc làm C++ hấp dẫn trên TopDev

3 Hiểu Lầm Về XPath Trong Web Automation

3 Hiểu Lầm Về XPath Trong Web Automation

Bài viết được sự cho phép của vntesters.com

Nhận diện web elements (element identification) là bước không thể thiếu khi automate web testing. XPath (được W3C khuyên dùng) chính là giải pháp tối ưu cho vấn đề này. Đa số các web automation tools đều hỗ trợ XPath, kể cả Selenium WebDriver. Dù vậy, sử dụng XPath hiệu quả thành thục không dễ, đòi hỏi nhiều thời gian tìm hiểu và “khổ luyện”.

Bài viết sẽ giúp bạn vén bức màn bí ẩn về 3 lỗi lầm thường gặp khi sử dụng XPath và cách khắc phục chúng. Hy vọng bạn có thể tận dụng được tối đa sức mạnh của “vũ khí bí mật” này.

  10 Java Web Framework tốt nhất
  Biện hộ: Vì sao các Developer không test phần mềm của họ?

[1] XPath là property của web element

Hiểu XPath bằng phép so sánh này là xu hướng tự nhiên khi bạn mới học về XPath. Nhưng dần dần bạn sẽ thấy cách hiểu tương tự đó khá nguy hiểm. Giả dụ bạn copy XPath của 1 button (<input>) trên Chrome bằng cách right click lên web element và chọn Copy > Copy XPath:

3 Hiểu Lầm Về XPath Trong Web Automation

Bạn sẽ nhận được chuỗi sau:

//*[@id=”Login”]

Trong khi đó, nếu bạn dùng Firebug (1 add-on của Firefox) trên cùng button, bạn sẽ nhận được kết quả hoàn toàn khác biệt:

/html/body/div/table/tbody/tr[5]/td/input

Tại sao XPath “property” của cùng 1 web element lại không hề giống nhau chút nào, dù web element này không thay đổi?

Bởi vì XPath thực sự không phải là “property” của control. Theo định nghĩa, XPath chỉ là ngôn ngữ để miêu tả cách tìm kiếm 1 web element mà thôi. Do vậy, những tools khác nhau trả về XPath của 1 web element hoàn toàn khác nhau là chuyện “bình thường như bức tường”.

Điều này ngầm định rằng bạn phải là người quyết định XPath nào dễ đọc (readable) và ổn định (reliable) nhất để locate 1 web element.

Một số test automation tools như TestArchitect (sản phẩm của LogiGear) cung cấp sẵn chức năng construct XPath “đẹp”. Screenshot bên dưới minh họa XPath mà TestArchitect gợi ý cho bạn (cùng chỉ đến button trong 2 ví dụ phía trên).

3 Hiểu Lầm Về XPath Trong Web Automation

Đường dẫn này (//input[@id=’Login’]) “đẹp” hơn bởi vì:

  • Chi tiết hơn gợi ý từ Chrome (//*[@id=”Login”]). Đường dẫn của Chrome sẽ chấp nhận tất cả elements có ID = “Login” dù element đó thuộc loại gì. Giả sử trang web có 1 element <td> cùng ID = “Login”, đường dẫn Chrome có thể trả về kết quả sai.
  • Ít “dễ vỡ” hơn gợi ý từ Firebug (/html/body/div/table/tbody/tr[5]/td/input). Giả sử <input> tag này được developer đổi sang <tr> thứ 8, đường dẫn Firebug sẽ trả về rỗng (null).

Dù XPath nào có “đẹp” đến đâu đi nữa, bạn vẫn phải là người quyết định cuối cùng.

[2] XPath không ổn định

Ấn tượng này cũng dễ hiểu vì đôi lúc test run của bạn fail trên Firefox vì ban đầu bạn capture trên Chrome và ngược lại. Cẩn thận điều tra một chút bạn sẽ thấy có sự khác biệt.

Trên Chrome:

//input[@id=’stdinput-00001′]

Trên Firefox:

//input[@id=’stdinput-0000A’]

Đây có thể là kết quả của việc developer generate elements động, một kỹ thuật khá phổ biến khi phát triển web apps. Có thể trong lúc code, anh chàng developer nào đó đã gắn liền việc tạo web elements vào loại browser. Đây là việc làm đi ngược với tiêu chí tăng testability. Dù vậy, đôi lúc lỗi lầm vẫn xảy ra.

Nếu bạn không để ý kỹ, bạn có thể đổ lỗi cho XPath. Nhưng thực tế kẻ tội đồ không phải XPath mà là cách generate ID cho controls đặc dị trên. Trong lúc chờ đợi developer fix sự bất đồng bộ này để tăng testability, bạn có thể tiếp tục công việc testing bằng 1 thủ thuật nho nhỏ như sau:

//input[contains(@id, ‘stdinput-00001‘) or contains(@id, ‘stdinput-0000A‘)]

Chúc mừng! Tests của bạn đã có thể chạy thành công trên cả 2 browsers.

[3] XPath là “silver bullet”

Trong tiếng Anh, cụm từ “silver bullet” miêu tả 1 giải pháp one size fits all (một câu trả lời cho mọi vấn đề). Phụ thuộc vào XPath quá mức mà không cẩn thận phân tích và thấu hiểu web apps bạn đang test sẽ làm bạn hết sức ngỡ ngàng khi nhận được kết quả failed bất ngờ. Cần hiểu rằng cùng 1 XPath có thể trả về nhiều elements khác nhau tùy vào tình huống. Ví dụ:

//a[.=’Mac’]

Khi bạn dùng XPath trên, bạn muốn lấy <a> element này:

3 Hiểu Lầm Về XPath Trong Web Automation

Nhưng bất ngờ thay, trong thực tế bạn nhận được element này:

3 Hiểu Lầm Về XPath Trong Web Automation

Do vậy, để chắc chắn luôn lấy đúng element, bạn nên đầu tư thời gian mổ xẻ và hiểu rõ về cấu trúc trang web mình đang test. Trong ví dụ trên, bạn có thể dễ dàng phân biệt 2 web elements bằng ancestor của chúng .

XPath của search result (case #1):

//div[@id=’content’]//a[.=’Mac’]

XPath của breadcrumb button (case #2):

//div/ul/li/a[.=’Mac’]

Kết luận

Hy vọng rằng làm sáng tỏ 3 hiểu lầm này có thể giúp bạn hiểu XPath, nhận diện element khi viết test case dễ dàng và test suite của bạn sẽ chạy ổn định hơn.

Bài viết gốc được đăng tải tại vntesters.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Phân chia dữ liệu – Sharding/Data Partitioning

Phân chia dữ liệu

Bài viết được sự cho phép của tác giả Edward Thiên Hoàng

Phân chia dữ liệu (Sharding) là một giải pháp chia nhỏ một Database lớn thành nhiều Database nhỏ, ta có thể phân tách từng bảng hoặc cả một DB ra nhiều phần nhỏ đặt ở nhiều máy chủ (server) khác nhau. Điều này sẽ giúp cho hệ thống DB của chúng ta đạt được các tính chất khả năng bảo trì (manageability), hiệu xuất (performance), tính sẵn sàng (availability), và cân bằng tải (load balancing) của ứng dụng. Và giải pháp này cũng giảm chi phí cũng như tính mở rộng (scalability) để scale up DB bằng cách dùng nhiều server nhỏ gộp lại hơn là nâng cấp một server lớn.

  26 công cụ và kỹ thuật trong Big Data có thể bạn chưa biết
  Dữ liệu lớn (Big Data) là gì? Đặc điểm và ứng dụng của Big Data

Phân chia dữ liệu - Sharding/Data Partitioning

NHỮNG CÁCH THỨC PHÂN CHIA DỮ LIỆU

Ta có 3 cách thức Sharding dữ liệu như sau:

  1. Horizontal sharding
    Là cách chia cùng dữ liệu của cùng một bảng (table) ra nhiều DB khác nhau. Ví dụ ta có bảng dữ liệu thông tin về người dùng, ta sẽ dựa trên location của người dùng để quyết định nó nằm ở DB nào, ví dụ người dùng ở Sài Gòn thì sẽ chứ ở DB_SG, thông tin người dùng ở Biên Hòa sẽ nằm ở DB_BH hay thông tin người dùng ở Vĩnh Long sẽ nằm ở DB_VL.
    Giải pháp này có một vấn đề là ta phải chọn nơi dữ liệu Sharding rất cẩn thận để không gây mất cân bằng (unbalanced) giữa các DB dẫn tới rất có thể có một vài Server sẽ thành điểm nóng (hot spot), ví dụ người dùng ở Sài Gòn chắc chắn là đông hơn rất nhiều lần người dùng ở Biên Hòa hay Vĩnh Long.
  2. Vertical sharing
    Là cách sharding dữ liệu dựa trên tính năng (feature) của hệ thống. Ví dụ ta thiết kế một hệ thống chia sẻ ảnh giống Instagram, ta sẽ lưu thông tin của User vào DB_Users, lưu thông tin ảnh họ up lên trên một DB khác là DB_Photos và thông tin danh sách những người họ follow ở một DB thứ 3 là DB_Follow.
    Cách làm này rất là rõ ràng dễ để implement và không làm ảnh hưởng lớn đến ứng dụng, nhưng khi hệ thống lớn dần lên thì dữ liệu cũng lớn dần theo, do đó ta lại phải thực hiện sharding tiếp những DB trên từng feature (bởi vì 1 DB không thể sử lý 10 tỷ bức ảnh của 140 triệu user được).
  3. Directory Based sharding
    Cách này sẽ yêu cầu ta phải thiết kế một “lookup service” có tác dụng quyết định ánh xạ (mapping) dữ liệu sẽ nằm ở đâu, DB nào. Mỗi khi có request ghi hoặc đọc sẽ thông qua lookup service để mapping vị trí sẽ đọc và ghi. Khi business mở rộng số lượng server có thể tăng lên mà không ảnh hưởng hay đòi hỏi ứng dụng phải thay đổi theo.
Phân chia dữ liệu - Sharding/Data Partitioning

NHỮNG TIÊU CHÍ ĐỂ PHÂN VÙNG DỮ LIỆU

Bên trên ta đã tìm hiểu và các method để sharding dữ liệu, giờ ta hãy tìm kiểu sâu hơn về các tiêu chí để phân vùng dữ liệu.

  1. Phân vùng theo key hoặc hash
    Hệ thống sẽ áp dụng các hàm băm (hash function) cho một hoặc nhiều các key chính trong dữ liệu (thường là ID) để xác định ra một con số của phân vùng nó đang nằm. Ví dụ: nếu hệ thống có 100 máy chủ DB và ID của bản ghi sẽ tự tăng lên mỗi lần một bản ghi mới được chèn. Trong ví dụ này, hàm băm có thể là ‘ID% 100, từ đó ta có thể xác định vị trí của dữ liệu. Cách tiếp cận này cần đảm bảo phân bổ dữ liệu thống nhất giữa các máy chủ. Nhưng cách làm này có một điểm yếu là mỗi khi ta thay đổi số lượng Server tăng hoặc giảm thì hàm băm cũng sẽ phải thay đổi theo và sẽ xuất hiện hiện tượng xáo trộn tập dữ liệu trên mỗi server, và đòi hỏi ta phải phân phối lại dữ liệu và xuất hiện độ trễ dữ liệu. Có một cách giải quyết vấn đề này là sử dụng Consistent Hashing (hàm băm nhất quán).
  2. Phân vùng theo danh sách (list)
    Cách phân vùng sẽ được quyết định gán một danh sách các giá trị ngay từ đầu, từ đó mỗi lần ghi một bản ghi mới ta sẽ tìm ra giá trị của bản ghi nằm ở phân vùng nào và ghi vào đó. Ví dụ ta sẽ quyết định nhóm tất cả các người dùng ở Ai-len, Na Uy, Thụy Điển, Phần Lan và Đan Mạch và một phân vùng có tên là Nordic (Bắc Âu).
  3. Phân vùng vòng tròn (round-robin) 
    Cách phân vùng này rất đơn giản là mỗi lần có thao tác ghi ta sẽ ghi vòng tròn quanh các phân vùng có sẵn. Cách làm này đơn giản nhưng rất khó để xác định dữ liệu nào ở đâu lấy ra khi cần.
  4. Phân vùng tổng hợp
    Là cách tổng hợp các giải pháp trên thành một giải pháp mới. Ví dụ ta có thể áp dụng phân vùng theo Key/Hash và sau đó xác định được key rồi ta sẽ áp dụng tiếp phân vùng theo danh sách để chứa key sau khi hash vào một danh sách cụ thể nào đó. Consistent Hashing có thể được coi là cách phân vùng tổng hợp.

CÁC VẤN ĐỀ KHI SHARDING DỮ LIỆU

Vì việc dữ liệu sẽ bị phân tán đi nhiều Server khác nhau do vậy sẽ phát sinh một vài vấn đề khi sharding dữ liệu như sau:

  1. Joins and De-normalization
    Bởi vì việc dữ liệu ở các bảng được phân bố và trải rộng đi nhiều DB/Server khác nhau nên việc join bảng dữ liệu là điều rất khó khăn và cũng không đem lại hiệu xuất bởi vì việc dữ liệu phải được queries từ nhiều máy chủ khác nhau. Để giải quyết vấn đề này ta có thể thiết kế dữ liệu dạng non-relationship DB hay còn gọi là NoSQL, giống như MongoDB hay Cassandra hai hệ NoSQL rất nổi tiếng và hỗ trợ Sharding vô cùng tốt. Tuy nhiên việc này ta phải chấp nhận rủi ro việc không nhất quán dữ liệu (inconsistency)
  2. Referential integrity
    Cũng vì lý do trên về việc truy vấn chéo dữ liệu giữa các DB nằm trên các máy chủ khác nhau là bất khả thi, do vậy việc ràng buộc khóa ngoại để bảo đảm sự toàn vẹn dữ liệu cũng là một điều vô cùng khó khăn. Hầu hết RDBMS không hỗ trợ các ràng buộc khóa ngoại trên các cơ sở dữ liệu phân tán trền nhiều server. Do vậy để đạt được điều này ta phải thực hiện điều này trên mã ứng dụng (code), điều này sẽ tăng tính phức tạp của ứng dụng.
  3. Rebalancing
    Trong suốt quá trình hệ thống vận hành có rất nhiều lý do ta thay đổi các chiến thuật hay cách thức Sharding dữ liệu, như business tăng trưởng yêu cầu thêm Server… Và mỗi khi như vậy ta phải tái cân bằng (rebalancing) dữ liệu trên tất cả các Server, có nghĩa là dữ liệu phải được phân phối lại trên toàn bộ server. Để làm được điều này mà không có độ trễ (downtime) là cực kỳ khó khăn. Mô hình sharding “Directory Based” có khả năng rebalancing tốt nhất nhưng lại tăng độ phức tạp của ứng dụng và tạo thêm một single point of failure (ví dụ “lookup service”).
    Tóm lại với Sharding thì mô hình sharding với key/hash với Consistent Hashing hiện tại là giải pháp tối ưu nhất cho việc Rebalancing.

Theo medium

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 1)

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Chào bạn! Lại là tôi Xuân Quỳnh đây. Bạn vẫn háo hức về những kiến thức cực kỳ cơ bản trong loạt bài lập trình C cơ bản này chứ? :))

  1001 Tips: Con trỏ và hàm (Pointer & Function) trong C++

  Sử dụng lệnh printf hiển thị câu chào ra màn hình

OK, bài trước các bạn đã làm quen với 1 lệnh cơ bản là printf, thuộc thư viện stdio.h. Rất hay dùng để in ra màn hình các đoạn text, các con số và nhiều thứ khác nữa. Tôi đã hứa là làm 1 hàm printf tương tự, nhưng nó thuần Việt 😀 Aha, tôi việt hóa hàm này cho bạn biết nha. Nhắc lại chương trình cũ của chúng ta như sau:

#include < stdio.h >
void main()
{
   printf(“Chao em C xinh dep”);
}

OK, bây giờ chúng ta sẽ thay thế hàm printf ở trên bằng hàm, tôi đặt tên nó là inramanhinh(“In cái gì đó trong này”) :))

Bây giờ tôi giới thiệu khái niệm mới là thủ tục. Nếu bạn nào hồi cấp 3 mà cày Pascal thì biết thủ tục là như nào rồi. Tôi nhắc lại theo cách bình dân như sau:

Thủ tục là việc nhóm các câu lệnh lại để xử lý 1 việc nào đó theo mong muốn của lập trình viên. Ở đây là tôi nhóm việc in ra màn hình thành 1 thủ tục có tên như trên. Rồi, từ khóa cho việc dịnh nghĩa là void <Tên thủ tục>. Ở đây là:

void inramanhinh(char* caicaninra)

Bạn choáng ngợp chưa? Đừng sợ, tôi sẽ chỉ cho bạn hết sợ nha. Ở trên tôi có từ khóa void. void là gì vậy trời? Ồ đó là 1 từ khóa của C, quy định cho việc viết thủ tục. Sau đó là 1 cái tên, bạn muốn đặt như nào cũng được, nhưng nhớ cho tôi 1 số quy tắc đặt tên như sau:

  • Tên thì không có dấu cách ở giữa. Chẳng hạn:

void in ra man hinh(char* caicaninra)

là sai! chứa dấu cách là em C nó không chơi đâu dấy, em ấy cần sự liên tục, anh em mà cứ đứt đoạn là em ấy chê yếu ngay :))

  • Tên không được trùng với các từ khóa của C. Từ khóa của C thì nhiều lắm, tôi copy pase cho bạn đọc nè:
auto double int struct
break else long switch
case enum register typedef
char extern return union
continue for signed void
do if static while
default goto sizeof volatile
const float short unsigned

Đó, nhưng bạn thích đọc thì đọc, không thích thì thôi 😀 Lúc nào cần cái nào thì quay ra đọc thì học nó dễ mà đỡ nhớ nhiều nhức đầu nạ :3

Bạn đặt tên thủ tục thì tránh mấy cái từ này cho tôi là ok 😀

  • Tên không được bắt đầu bằng  ký tự đặc biệt ((, #..) mấy cái đó tránh cái nà.

Rồi còn nhiều quy tắc lắm nhưng mà bạn cũng không cần mất quá nhiều thời gian cho việc này. Bạn chỉ cần nhớ đặt tên theo cách của bạn, 1 cái tên của bạn và tên đó nên gợi nhớ cái thủ tục của bạn làm cái gì.

Nhắc lại hàm đang nghiên cứu:

void inramanhinh(char* caicaninra)

bên trong 2 cái dấu ngoặc là cái gì mà hoa bay bướm lượn vậy nhỉ? bạn kéo lên keyword và xem từ khóa char. Vậy char là gì? Tiếng anh tin học char là viết tắt của character: ký tự 😀

Là kiểu dữ liệu thôi chứ không có chi mô nà. Ngoài char ra tôi nói thêm:

int  = integer = số nguyên

float = số thực

long: số nguyên nhưng phạm vi lớn hơn int

double: số thực nhưng phạm vi lớn hơn float. Nó được định nghĩa kiểu dữ liệu có mũ.(cái này là cái gì nghiên cứu sau nha=)))

Kiể dữ liệu là việc bạn chọn lựa để sử dụng trong chương trình. Ví dụ chương trình của bạn đếm đếm cây, đếm vịt gà, (đếm được) thì dùng kiểu nguyên là int. đếm nhiều quá thì cho hẳn cái long cho nó máu. Tuy nhiên cái gì cũng có giới hạn cả, máy tính cũng đếm được bao nhiêu đó rồi nó chịu 😀 Còn giửa sử giải phương trình bậc 2 thì bạn cần dùng kiểu float hoặc double, vì phương trình bậc 2 giải cho cả số thực mà. Tôi lấy ví dụ như vậy nhằm nhắc bạn 1 điều. Tùy thuộc vào bài toán mà chọn kiểu dữ liệu, chứ không phải cứ thích int thì cho int, thích float thì cho float đâu nha 😀 Nhớ nha, kỹ năng cơ bản đó. Không đến lúc sai kết quả lại bảo C ngâu :))

Vậy còn sau char tôi thêm 1 dấu * để làm cái gì rứa? Aha, nó còn được gọi là con trỏ. Con trỏ là cái gì thế? Ồ, con trỏ là con trỏ :)) Con trỏ không phải là con trỏ chuột bạn di di trên màn hình đâu nha. Hồi mới học C tôi cứ nghĩ thế mới tài :)) Con trỏ có gì hay vậy? Tôi vinh hạnh giới thiệu cho bạn, con trỏ là đặc quyền của C/C++ mà không một ngôn ngữ nào có được đặc quyền này. Cùng lắm sau này có thằng objective-c được phát triển từ C cũng có thôi.

Vậy con trỏ thì ta nên hiểu như nào cho đúng?

Ở đây nếu tôi không dùng dấu * thì nó hiểu đó là kiểu char bình thường như cân đường hộp sữa. Bạn gặp * bạn hiểu đó là kiểu dữ liệu con trỏ. Con trỏ hơn ở biến thông thường điểm nào, tôi sẽ làm rõ như sau:

Giả sử bạn cần sử dụng biến để nhập ký tự, bạn dùng char. 1 ký tự bạn khai báo như sau:

char < tên biến >

Ví dụ:

char a;

tên biến nó cũng có quy tắc đặt tên, nhưng bạn nên đặt tên gợi nhớ với cái bạn cần. Bạn có thể đặt tên:

char conlon; char contrau; char hihi;

thoải mái, dài bao nhiêu cũng được, nhưng mấy cái tên cần nhắc nhớ cho bạn nó để làm gì. Đằng sau bạn thêm cho tôi 1 dấu ; nhằm mục đích kết thúc quá trình đặt tên biến.

Vì nó là lưu 1 ký tự cho nên bạn có thể gán giá trị cho biến này. Giả sử tôi có đoạn chương trình:

char c;
c = 'm';

Tôi khai báo 1 biến c. sau đó tôi gán biến c là ký tự m. Bạn để ký tự m trong 2 dấu nháy đơn nhé.

Bây giờ để in ra ký tự c này tôi viết:

printf("c = %c", c);

Chương trình đầy đủ:

#include < stdio.h >
void main()
{
   char c;
   c = 'm';
   printf("c = %c", c);
}

Kết quả trên màn hình:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 1)

Đấy nó in ra c = m 😀

Bạn nào chưa biết gõ lệnh thì vui lòng xem bài 1 nha.

Bạn quay lại câu lệnh này tôi giải thích:

printf("c = %c", c);

%c là cái gì thế? %c là 1 cái nhãn, bạn hiểu nó sẽ thay thế ký tự vào đó. c = character. Nó sẽ đưa giá trị của biến c vào %c này, nên nó mới in ra như trên :)) em C em ấy quy định như vậy thì mình phải theo thôi =))

Ngoài %c ta còn có 1 số nhãn khác:

%d = để in ra số nguyên (d = double)

%f = để in ra số thực.(f = float)

Nếu bạn muốn in ra 2 số thập phân sau dấu phẩy thì thêm:

%2.2f: đằng trước bạn đặt bao nhiêu cũng được, đằng sau viết số 2 thì nó ra 2 số sau dấy phẩy. Tương tự %d cũng vậy nha :))

ví dụ: printf(“so thuc = %2.2f”, biensothuc);

%p = in ra địa chỉ con trỏ (p = pointer)

Ví dụ: printf(“dia chi cua p = %p”, pa);

=)) Bạn thấy mệt chưa? tôi khuyên bạn 1 câu như này, bạn đọc tới đâu trong bài của tôi thì bạn gõ code tới đó nhé 😀 học lập trình thì phải lập trình, như vậy mới nhớ dai được. Gõ lại mấy đoạn code đầy đủ của tôi bạn nhé.  Đọc qua thì nó nhanh quên lắm. Ok, hít 1 hơi và tiếp tục.

Tôi quay lại với vấn đề con trỏ. Vậy là với biến thông thường, bạn khai báo theo kiểu dữ liệu bạn muốn + tên biến bạn nghĩ ra. Thì lúc đó, máy tính của bạn sẽ cấp cho bạn 1 vùng nhớ để lưu. Hoàn toàn tự động. Bạn chỉ thấy được biến và giá trị của nó thôi. Thế còn bây giờ, bạn muốn xem biến đó nằm ở đâu trong máy tính của bạn? Bạn dùng cách này. Bạn them dấu & trước biến của bạn. Ví dụ &a thì nó lấy địa chỉ của bạn. Chương trình thí dụ:

#include < stdio.h >
void main()
{
    char c;
    c = 'm';
    printf("Dia chi cua c = %p", &  c);// ban viet lien dau &  nhe, thang wp ngau qua
}

Ở trên, bạn thay %c bằng %p để in ra địa chỉ. Bạn thêm dấu & trước c để lấy địa chỉ.

Kết quả như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 1)

Bạn thấy gì không? kết quả là 0028FF2F :)) Trông hoa mắt chưa. Vừa số vừa chữ cơ :v

Chữ cái F trên nghĩa là gì? Nó đang in ra hệ 16 bạn nhé. Hệ 10 bạn học từ hồi cấp 1 là các số từ 0 tới 9. Lên cấp 2, cấp 3 bạn học thêm hệ 16 với các số từ 0 tới 9 và các chữ cái: A để mô tả 10, B = 11, C= 12, D = 13, E = 14, F = 15. 😀

Ai quan tâm tới cách đổi cơ số 10 sang cơ số 16 không? Rảnh tôi sẽ hướng dẫn, tạm thời bài này bạn hiểu địa chỉ đó cũng là 1 cái số, số to quá nên dùng cơ số 16 để in cho tiện.

Vậy ví dụ trên, bạn hiểu biến c lưu giá trị m và nằm tại địa chỉ 002FF2F. Trên máy bạn địa chỉ này chắc chắn không giống tôi đâu :))

Vậy, bạn hiểu à hóa ra biến mà mình sử dụng được máy tính cấp cho 1 cái địa chỉ, 1 ô nhớ, 1 con số nằm trên vùng nhớ máy tính. Và thường thì ta mới học lập trình không quan tâm mấy tới địa chỉ này. Tuy nhiên học sâu về C lại hay chơi với các địa chỉ này, nhảy qua địa chỉ này tới địa chỉ khác. Ví dụ:

#include < stdio.h >
void main()
 {
   char c1;
   char c2;
   char* pc;
   c1 = 'm';
   c2 = 'n';
   printf("Dia chi cua c1 = %p \n", & c1); //viet lien dau & va c1 nhe
   printf("Dia chi cua c2 = %p \n", & c2);// wp ngau, wp ngau :((
   pc = & c1;
   printf("Dia chi cua pc = %p \n", pc);
   pc = & c2;
   printf("Dia chi cua pc = %p \n", pc);
}

Bạn vui lòng viết từng đoạn lệnh trên vào notepad của bạn và build theo hướng dẫn các bài trước. Nhớ là viết từng đoạn 1 cho tôi nhé :)) Bắt buộc đấy. Để các bạn nhớ dai hơn.

Ở trên tôi có thêm \n để xuống dòng in cho dễ đọc thôi nạ.

Kết quả như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 1)

Rồi bây giờ ta phân tích từng đoạn 1:

char c1;
char c2;
char* pc;

Tôi khai báo 2 biến thường và 1 biến con trỏ để lưu ký tự.

c1 = 'm'; c2 = 'n';

Tôi gán c1 cho ký tự m, c2 cho ký tự n.

printf("Dia chi cua c1 = %p \n", & c1); printf("Dia chi cua c2 = %p \n", & c2);

Tôi in địa chỉ của từng thằng ra.

pc = & c1; //viet lien nhe, do loi cua wp printf("Dia chi cua pc = %p \n", pc);

Tôi gán pc cho địa chỉ c1, rồi tôi in ra.

Tương tự tôi làm với c2. Bây giờ bạn kéo lên xem lại kết quả.

Rõ ràng bạn thấy thằng pc nó là con trỏ và nhảy qua lại giữa 2 địa chỉ biến thường c1 và c2. Vậy rõ ràng biến con trỏ rất chi là hiếu động, ổng nhảy tự do lung tung đi đâu cũng được. Bạn dùng câu lệnh sau để in ra giá trị của ông pc. Chương trình full thêm 2 dòng:

#include < stdio.h >
void main()
{
 char c1;
 char c2;
 char* pc;
 c1 = 'm';
 c2 = 'n';
 printf("Dia chi cua c1 = %p \n", &  c1);
 printf("Dia chi cua c2 = %p \n", &  c2);
 pc = & c1; //viet lien dau & va c1 nhe
 printf("Dia chi cua pc = %p \n", pc);
 printf("Gia tri cua pc = %c \n", *pc);
 pc = & c2;
 printf("Dia chi cua pc = %p \n", pc);
 printf("Gia tri cua pc = %c \n", *pc);
}

Kết quả như sau:

Tự tạo một hàm printf thay thế cho hàm printf mặc định trong thư viện stdio.h (phần 1)

Bạn xem kết quả và ngẫm xem nào. Ngẫm nào ngẫm nào…

Bạn thấy đó, bạn tưởng tượng các giá trị c1 c2 là 2 vùng nhớ khác nhau trong máy tính. Còn cái ông pc là 1 ông thích trỏ tới đâu cũng được. Ông trỏ vào đâu thì coi như ông có luôn biến thường đó, ổng muốn hấp diêm hay làm gì biến đó cũng được =))

Bạn đã thấy con trỏ mạnh mẽ chưa? Chưa đâu. Càng sau bạn mới thấy được cơ.

Tôi viết cũng hơi mệt rồi. Thôi ta kết thúc bài học luôn.

Quay lại với chương trình đầu tiên, như cái tiêu đề. Ta sẽ tiếp phần 2 vào bài sau nha các tình yêu 😀

Note: Bạn chú ý dòng này cho tôi:

#include < stdio.h >

Tôi phải đặt dấu < và > ra xa vì thằng wp nó tự động mã hóa. Bạn viết code thì viết sát vào cho tôi nhé. Thứ 2 là cái dấu & và các biến đằng sau cũng viết liền nha.

Chú ý cả code style, tôi chưa biết cách chỉnh trên wp. chả lẽ tôi chụp hình code nhỉ :3
Happy

Bài viết gốc được đăng tải tại quynhlaptrinhc.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Software Architect (SA)

Software Architect

Bài viết được sự cho phép của tác giả Tino Phạm

Là dân IT hẳn mọi người không còn xa lạ với cụm từ Software Architect (SA) – ở đây mình tạm dịch là kiến trúc sư phần mềm. Tuy nhiên không phải ai cũng hiểu được vai trò, trách nhiệm, công việc thực sự và con đường sự nghiệp của một SA. Đây là những câu hỏi mà mình đã từng đặt ra khi bước vào những nấc thang đầu tiên của vị trí này. Mình tự đi tìm lời giải đáp cho bản thân.

  10 Công cụ Go-To Tech dành riêng cho các Software Developer
  Các nền tảng tuyển dụng tốt nhất dành cho Software Engineer l Cập nhật năm 2022
Software Architect (SA)

Phân loại kiến trúc sư phần mềm

Thật ra có nhiều cách để phân loại kiến trúc sư phần mềm. Tuy nhiên, ở đây mình sử dụng cách phân loại của Microsoft. Đây cũng là một cách thức phân chia khá phổ biến trong ngành phần mềm hiện nay.

Tên Mô tả
Kiến trúc sư nghiệp vụ (enterprise architect) Là cầu nối giữa chủ sở hữu sản phẩm và đội ngũ kĩ thuật. Họ là những người có kinh nghiệm chiều sâu trong lĩnh vực mà sản phẩm đang xây dựng. Chịu trách nhiệm trong việc xây dựng và phát triển yêu cầu – thiết lập viễn cảnh, bộ khung của môi trường IT trong sản phẩm.
Kiến trúc sư hạ tầng (infrastructure architect) Là người chịu trách nhiệm trong việc thiết lập, xây dựng giải pháp về cơ sở hạ tầng IT (ví dụ: mạng, các vấn đề bảo mật, thiết bị/ phương thức lưu trữ, ..) trong sản phẩm để đáp ứng nhu cầu của doanh nghiệp.
Kiến trúc sư giải pháp (solution architect) Là người chịu trách nhiệm trong việc thiết kế, xây dựng giải pháp cho những yêu cầu của sản phẩm.
Kiến trúc sư kĩ thuật (Technology-specific architect) Là người chịu trách nhiệm về một hoặc một số lĩnh vực kĩ thuật cụ thể.

Trong một số công ty hiện tại ở Việt Nam, có một vị trí gọi là Technical Architect (kiến trúc sư kĩ thuật) trong tổ chức. Vị trí này chịu trách nhiệm cho việc phân tích, đánh giá giải pháp, xây dựng kiến trúc hệ thống. Nếu ánh xạ với cách phân loại trên thì TA chính là Solution Architect.

Xem ngay việc làm Solution Architect mới nhất trên TopDev

Những tính cách cần thiết của một kiến trúc sư phần mềm giỏi

Cho dù bạn có là kiến trúc sư phần mềm nào, thì dưới đây là những tính cách bắt buộc phải có để đạt được đỉnh cao của nghề này:

  1. Nhạy bén về kinh tế: mọi kiến trúc sư khi đưa ra giải pháp cho bất cứ bài toán nào cũng đều phải cân nhắc chi phí, lợi ích tương quan của doanh nghiệp. Đây là yếu tố then chốt đánh giá hiệu quả của một giải pháp.
  2. Có tầm nhìn xa: khi tham gia vào một dự án, kiến trúc sư phải cân nhắc những giải pháp, công nghệ sắp xuất hiện, xem xét những thay đổi gần đây trong lĩnh vực công nghiệp đang phát triển… và làm cách nào để tận dụng tối đa giải pháp hiện tại trong tương lai.
  3. Nghiên cứu kĩ thuật mới: một kiến trúc sư phải luôn luôn nghiên cứu những hướng kĩ thuật mới, từ kiến trúc IT cho đến những ứng dụng và xu hướng phát triển ứng dụng.
  4. Hiểu và có khả năng ứng dụng những framework, kiến trúc hệ thống, phương pháp luận trong quá trình phát triển phần mềm
  5. Có thể làm việc trên những thông tin còn chưa rõ ràng.
  6. Khả năng truyền đạt và giao tiếp.

Làm sao để tôi có thể trở thành một kiến trúc sư phần mềm?

Kiến trúc sư phần mềm là đỉnh cao của thang nghề nghiệp khi bạn chọn đi theo con đường kĩ thuật. Để trở thành một kiến trúc sư phần mềm, bạn nên theo những bước sau:

  1. Định hướng rõ ràng về loại kiến trúc sư phần mềm bạn muốn trở thành.
  2. Xác định và xây dựng những kĩ năng cần thiết. Liên tục bổ sung kiến thức phù hợp cho loại hình kiến trúc sư mà bạn chọn.
  3. Không ngừng phấn đấu và khẳng định vai trò của một kiến trúc sư trong chính những dự án mà bạn đang tham gia.
  4. Cố gắng rèn luyện và lấy những chứng chỉ quốc tế về kiến trúc sư kĩ thuật của những tập đoàn công nghệ lớn (Microsoft hoặc Sun). Microsoft bạn cần lấy được MCA (Microsoft Certificate Architect). Đối với Sun, bạn cần lấy được chứng chỉ: SCEA (Sun Certificate Enterprise Architect).

Con đường để trở thành một kiến trúc sư phần mềm đỉnh cao và chuyên nghiệp vẫn còn ở rất xa. Và có một điều mình luôn tâm niệm là: dù ở bất kì ngành nghề nào, vị trí nào – việc phấn đấu để đạt được đỉnh cao trong sự nghiệp cũng đều đem lại những lợi ích như nhau so với những vị trí hoặc ngành nghề khác.

Kiến trúc sư phần mềm (KTSPM) cần những gì?

KTSPM, trước hết, phải thấy xa hơn những gì mà một kĩ sư bình thường thấy và thực sự hiểu rõ về hệ thống. Có một chuyện khá là kì cục là các dự án hay bắt đầu bằng cách cho KTSPM viết ngày viết đêm ra một cái gọi là framework (framework ở đâu ra mà lắm thế), sau đó lui ra, và các kĩ sư bình thường sẽ nhào vô viết thêm tính năng, và chúng ta có một phần mềm. Sau đó có thể có chút trục trặc, chậm chạp thì các KSTPM này lại quay trở lại để dọn rác.

Nhưng hãy để tôi kể câu chuyện về dự án mà tôi đang làm đã. Đầu tiên chúng tôi có một KTSPM. Người này chuẩn bị mọi thứ, từ hệ thống build, database, Spring, Hibernate này kia, và cũng viết một ít làm mẫu. Và vì chỉ là làm giúp nên rời dự án nhanh chóng. Sau đó chúng tôi bỏ một thời gian dài loay hoay vừa muốn giữ cái nền này vừa muốn đập bỏ.

Khi yêu cầu phần mềm thay đổi và vấn đề nảy sinh thì cái nền rõ ràng là không phù hợp. Nhưng cái nền là do Kiến Trúc Sư (KTS) viết ra mà. Sự thiếu dứt khoát khiến cho mọi thứ trong hệ thống mà chúng tôi xây dựng vẫn còn khá là vá víu và không linh hoạt.

Trong giai đoạn này có hai người nữa, một người là KTS và một người gần được KTS. Nhưng họ cũng chỉ viết mã cho một vài phần. Có thể là những phần khó hơn, nhưng nó chỉ là một phần nhỏ của toàn bộ bức tranh. Và nó cũng chứa những sai lầm tiềm ẩn như những nhiều phần khác. Và nó cũng có thể được hoàn thành bởi những kĩ sư khác trong dự án, mặc dù có thể là phải có một chút hướng dẫn.

Nói tóm lại, những KTSPM đang làm những việc mà kĩ sư làm, chỉ là (có thể) ở một trình độ tốt hơn.

Vậy những sai lầm mà dự án tôi gặp phải và mắc kẹt là gì?

Có thể kể ra những thứ khá cơ bản, như bỏ qua các bước an ninh cơ bản (chống XSS, CSRF), không xây dựng một dạng protocol (hay interface) thống nhất cho các request, bỏ lơ vấn đề cache và performance (cache phía server, cache phía client), không có hệ thống build tự động, không có phương pháp chung để xử lí vấn đề cross-browser, ect.

Đây là những vấn đề có tác động quan trọng tới thiết kế của phần mềm, nên không thể giải quyết một sớm một chiều được. Dĩ nhiên, phần mềm là một hệ thống phức tạp mà khi đã đầy đủ các bộ phận thì việc thay đổi sẽ tốn kém. Vì vậy, không thể ngày hôm nay nghĩ về vấn đề này thì xây dựng nó một kiểu, rồi mai gặp hay chợt nghĩ về vấn đề khác thì sửa đối nó theo kiểu khác.

Tất nhiên KTS vẫn nên là người viết những thành phần quan trọng, để góp phần tạo ra một phần mềm có chất lượng tốt. Nhưng kĩ sư giỏi thì cũng có thể viết được những phần khó, họ cũng có thể đọc sách, tìm hiểu, suy nghĩ.

Vậy thì giá trị đặc biệt của KTSPM nằm ở chỗ nào? Tại sao họ đứng trên một cấp và lương cao hơn?

Theo tôi nghĩ đấy là vì kĩ sư giỏi là những người chỉ giải quyết được những vấn đề cục bộ, riêng rẽ, chứ không thể quan sát hệ thống một cách tổng thể.

KTSPM phải là người định hướng. Họ phải liệt kê ra được những yêu cầu, vấn đề, hoặc thử thách mà dự án sẽ đối mặt, trước mắt và tương lai. Họ phải xây dựng được những quy tắc chung để kĩ sư có thể tuân theo nhằm hạn chế sai sót. Họ phải biết phân bổ nhân lực cho hợp lí với từng phần việc. Và họ phải nắm tình trạng phát triển hiện tại của phần mềm để nhận ra những bài toán hay cải tiến cần được thực hiện một cách thực sự đúng đắn và dứt khoát.

Không chỉ nhìn xa hơn những kĩ sư, KTSPM còn phải cố gắng nhìn xa hơn những gì ông chủ nghĩ. Không phải là về kinh doanh, mà là về chức năng của phần mềm. Họ phải biết trừu tượng hóa các yêu cầu cụ thể để có cái nhìn bao quát cho chức năng mà trong đó yêu cầu của những người phân tích nghiệp vụ chỉ là một lựa chọn, một hướng hiện thực cụ thể.

Ý định của con người luôn thay đổi rất nhanh, và yêu cầu cũng vậy, nên không có lí do gì lập trình viên đặt niềm tin là những thứ họ phải làm hiện tại sẽ giống vậy mãi mãi. Chuẩn bị tốt cho những lựa chọn chưa xảy ra sẽ giúp phần mềm linh động với những nhu cầu, đòi hỏi từ thị trường. Và điều quan trọng là thấy trước thay đổi của hệ thống là nhiệm vụ của KSTPM, không cần ai khác phải nói ra, và họ sẽ không thể đổ lỗi đi đâu đó như người phân tích nghiệp vụ, hay người dùng nếu không thực hiện tốt nhiệm vụ này.

Chẳng hạn, hãy nói việc hỗ trợ bookmark cho những web application dùng AJAX nhiều. Nếu một trang web mà trạng thái của nó, như đang mở tab nào, đang hiện nội dung gì, không được thể hiện trên địa chỉ thì người dùng sẽ không thể bookmark để quay lại trạng thái đó một cách nhanh chóng được.

Tuy nhiên, yêu cầu phần mềm thường quên mất chuyện này, trong khi nếu không được thiết kế ngay từ đầu thì việc chỉnh sửa thiết kế của ứng dụng để hỗ trợ chức năng này sẽ khá rắc rối. Do nên KTSPM phải biết tự thấy trước và đáp ứng chức năng ngay khi chưa có yêu cầu.

Có thể tóm lại là KSTPM trước hết phải biết nhìn xa, nhìn trừu tượng, không chỉ xây nên framework mà còn những tiêu chuẩn, quy định, và đường lối cho dự án.

Có một câu hỏi khá thú vị như thế này: What technical details should a programmer of a web application consider before making the site public?

Nếu là bạn, bạn sẽ trả lời như thế nào?

Tham khảo:

https://fly2universe.wordpress.com/2011/11/03/ki%E1%BA%BFn-truc-s%C6%B0-ph%E1%BA%A7n-m%E1%BB%81m-anh-la-ai/

https://cnttqn.com/threads/kinh-nghiem-kien-truc-su-phan-mem-can-nhung-gi.3760.html

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Lộ trình để một ứng dụng thành công

Lộ trình để một ứng dụng thành công

Bài viết được sự cho phép của tác giả Trần Cảnh Lực

Một ứng dụng thành công cần phải có những yếu tố như tính thực tiễn, đáng tin cậy, thiết kế bắt mắt, đáp ứng nhu cầu người dùng….

Trước xu thế hiện nay, số người dùng điện thoại ngày càng tăng dẫn đến nhu cầu ứng dụng di động lên cao. Tuy nhiên, trước tài nguyên phần mềm phong phú để một ứng dụng lọt vào “mắt xanh” của người tiêu dùng không phải là điều dễ dàng.

  'Toát mồ hôi' phỏng vấn tuyển dụng vào Apple
  3 tools giúp bạn tăng hiệu năng của React App một cách bất ngờ

Những hình ảnh đồ họa dưới đây hướng dẫn một cách trực quan nhất cho quá trình này, hi vọng nó có thể giúp bạn điều gì đó trong con đường phát triển ứng dụng cho chính mình.

Lộ trình phát triển một ứng dụng Lộ trình phát triển một ứng dụng

Tóm tắt lộ trình phát triển một ứng dụng thành công:

1: Bạn có một ý tưởng ứng dụng?

Nếu thế, bạn cần phải xem ý tưởng đó có những gì được gọi là “HOT”, xu thế của google trong thời điểm hiện tại hoặc sắp tới. Bạn hãy tìm những từ khóa cho ứng dụng của bạn trên google, xem xếp hạng tìm kiếm của những từ khóa cho ứng dụng đó. Nếu idea đó thực sự “HOT” thì hãy tiếp tục thực hiện ứng dụng của bạn.

2: Bạn đã tiến hành nghiên cứu chiến dich marketing cho tên ứng dụng của bạn?

Có nhiều lý do tại sao điều này lại quan trọng bạn nên tìm hiểu qua về  chiến dich marketing cho tên ứng dụng. Nếu bạn chưa có một cái tên nào tốt hãy đi đến google adwords.

3: Bạn đã lấy ảnh chụp màn hình chất lượng và có một icon cho ứng dụng thực sự tốt?

Ấn tượng đầu tiên của người dùng khi tìm đến với ứng dụng của bạn là người dùng nhìn thấy tiềm năng của ứng dụng thông qua những hình ảnh minh họa, icon ứng dụng có bắt mắt, có những thứ người dùng mong chờ ở trong ứng dụng hay không để quyết định tải về.

4: Bạn đã gửi ứng dụng của bạn để xem xét?

Bạn có thể nghĩ rằng ứng dụng của bạn là hoàn hảo, nhưng một số người ngoài cuộc có thể cung cấp cho bạn một ý kiến để giúp bạn cải thiện chất lượng của ứng dụng của bạn. Bạn có thể tìm thấy nhiều trang web review ứng dụng, cộng đồng web đó sẽ được sẵn sàng để đánh giá ứng dụng của bạn.

5: Các bạn đã test ứng dụng của bạn với ba cái tên và mô tả cho ứng dụng khác nhau?

Vâng, Để đảm bảo rằng đối tượng của bạn hoàn toàn hiểu những gì ứng dụng của bạn, bạn có thể cần để chơi xung quanh với tên và mô tả ứng dụng của bạn một vài lần để kiểm tra nó hoạt động có giống như vậy không.

6: Theo dõi bảng review ứng dụng?

Tại thời điểm này, trong khi ứng dụng của bạn vẫn đang trên con đường thành công, tôi cho rằng không nên có quảng cáo trong ứng dụng. Để có được người dùng thích ứng dụng của bạn với đầy đủ tiềm năng của nó trước khi bạn kích hoạt quảng cáo. Ở giai đoạn này, bạn cần phải bắt đầu nhận được thông tin phản hồi của khách hàng thực sự. Những review không tốt từ khách hàng cần được bạn quan tâm hơn, đồng thời có những sự hồi đáp thông qua các phiên bản tiếp theo của ứng dụng.

7: Đẩy mạnh việc tải ứng dụng.

Có nhiều cách giúp bạn đẩy nhanh việc tải ứng dụng, thông qua việc chia sẻ ứng dụng lên các diễn đàn, báo chí hoặc bạn có thể sử dụng dịnh vụ quảng cáo ứng dụng từ các nhà quảng cáo như adwords, facebook, …Nhằm đẩy nhanh việc tải ứng dụng của bạn trong thời gian ngắn.

8: Bạn đã cập nhật ứng dụng của bạn hàng tháng không?

Trong GooglePlay, Apple store hoặc bất kỳ cửa hàng ứng dụng khác, điều quan trọng là bạn nên cập nhật ứng dụng của bạn khoảng một tháng một lần. Người sử dụng được thông báo về bản cập nhật này thông qua các cửa hàng ứng dụng và điều này khuyến khích người sử dụng để quay lại ứng dụng. Việc này cho thấy ứng dụng của bạn vẫn luôn được phát triển và ngày càng hoàn thiện hơn.

9: Bạn đã có gửi thông báo cho người dùng ( push notifications )?

Mỗi khi ứng dụng bạn có thông tin, tính năng gì mới bạn có thể thông báo cho người dùng biết thông qua push notifications, hoặc người dùng sau một thời gian dài không sử dụng ứng dụng bạn có thể gửi thông báo cho người dùng nhắc nhở quay lại sử dụng ứng dụng thường xuyên hơn.

10: Bây giờ xây dựng mạng ứng dụng của bạn.

Xây dựng mạng lưới ứng dụng của bạn cho phép bạn thúc đẩy các ứng dụng của bạn và xây dựng một lương khách hàng quen thuộc cho ứng dụng của bạn. Nó cũng cho khách hàng của bạn thấy rằng bạn là một nhà sản xuất ứng dụng thành công, tin cậy.

Tham khảo từ: developer-tech.com

Bài viết gốc được đăng tải tại blog.thangcodedao.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Rethinking the hjkl

Rethinking the hjkl

Bài viết được sự cho phép của tác giả Huy Trần

Chắc cũng có đôi lần mình nhắc tới vấn đề này trên blog, đại khái là từ khi xài vim, mình mắc phải một vấn đề khó chữa, đó là, có những lúc mình rơi vô trạng thái không muốn làm gì mà chỉ ngồi bấm hjkl để chạy đi chạy về trên file, từng dòng một, từng kí tự một…

Thực ra khi mình có làm việc thì cũng vậy, việc di chuyển từng dòng và từng kí tự một khiến cho tốc độ làm việc của mình giảm đi khá nhiều. Nên gần đây mình có thay đổi một tí trong cách mình xài vim.

  Cảm ơn Vim, mình đã dừng code bằng VS Code.
  Cách mạng 0.4 của Neovim: Floating Window

Đầu tiên, để di chuyển nhanh hơn, hiển nhiên là mình sẽ sử dụng motion. Ví dụ nhảy tới trước 10 dòng (10j) hay nhảy lui 5 dòng (5k), hay nhảy tới một dòng thứ n bất kỳ (:n).

Tiếp theo, là nhảy nhanh đến một kí tự trong một dòng bằng f hoặc F, ví dụ, bấm f kèm theo một kí tự để nhảy đến vị trí tiếp theo có kí tự đó trên dòng hiện tại. Bấm ; để lặp lại thao tác nhảy đó với kí tự tiếp theo.

Lệnh F nhảy hướng ngược lại với lệnh f.

Giờ mới tới phần thú vị. Đó là remap lại phím h và l thành b và w (để dịch chuyển theo word thay vì character). Làm như vậy sẽ giúp di chuyển nhanh hơn, và khi cần di chuyển chậm lại thì mình map tổ hợp Shift + L / Shift + H về dạng dịch chuyển từng character.

nnoremap L l
nnoremap H h
nnoremap l w
nnoremap h b

Mặc định, vim có tổ hợp Ctrl + D và Ctrl + U để nhảy lên xuống từng trang màn hình, nhưng bố trí phím như vậy hơi phiền phức đối với mình nên mình cũng remap lại thành Ctrl + K và Ctrl + J:

nnoremap <C-k> <C-u>
nnoremap <C-j> <C-d>

Thêm nữa, vì có một thời gian xài Emacs nên mình cảm thấy tổ hợp phím Ctrl + F / Ctrl + B để dịch chuyển trái phải trên một dòng rất tiện dụng, nhất là khi đang ở trong INSERT mode, kèm theo đó là tổ hợp phím Ctrl + A / Ctrl + E để nhảy tới đầu / cuối của một dòng, cũng trong INSERT mode, cho nên đem cái này vô trong vim luôn:

inoremap <C-f> <Right>
inoremap <C-b> <Left>
inoremap <C-e> <C-o>$
inoremap <C-a> <C-o>^

Vậy mới thấy cái lợi của việc xài nhiều editor khác nhau  đi nhiều học nhiều, ăn cắp nhiều thứ về mix lại với nhau rồi xài.

Bài viết gốc được đăng tải tại thefullsnack.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Vùng lùng bùng

Vùng lùng bùng

Bài viết được sự cho phép của tác giả Huy Trần

Người ta nói nhiều về cái gọi là vùng an toàn, đại khái nó là một trạng thái về mặt tinh thần, mà khi đặt mình trong trạng thái đó, bạn cảm thấy vui vẻ, thoải mái, không áp lực, làm việc gì cũng thấy thuận lợi và thắng lợi, lý do? tại vì ở trong đó bạn chỉ cần sử dụng 30% khả năng, trí tuệ, tinh thần và thể lực của bản thân.

  "Dân làm Product khác hoàn toàn 180 độ với dân làm outsourcing"
  Bí kíp để host apps hoàn toàn miễn phí

Tác hại của vùng an toàn là bạn chẳng đi tới đâu cả, không tiến, không tới, không học thêm được gì, cũng chẳng thể nào giàu có hơn cả về kiến thức, kinh nghiệm lẫn tài chính.

Người ta cũng nói, bước ra khỏi vùng an toàn, bạn sẽ đến vùng nguy hiểm, nơi mà bạn sẽ được trải nghiệm, hay nếm trải, học hỏi nhiều hơn, cố gắng nhiều hơn và gặt hái cũng nhiều hơn.

Nhưng mà thực ra chuyện đó không hoàn toàn đúng.

Ngay khi bước ra khỏi vùng an toàn, nơi mà bạn đặt chân đến không phải vùng nguy hiểm mà là vùng lùng bùng. (danh từ được phát minh bởi một triết gia vô tiếng ở thế kỷ 21)

Tại đây, bạn đánh mất bản thân, không biết mình sẽ đi về đâu, trong lòng cực kì hoang mang và không biết được mình nên làm cái gì tiếp. Những thứ bạn nghĩ mình đã biết, thì bạn đã biết hết rồi. Nhưng bạn không biết là mình chưa biết cái gì, và cần biết mình chưa biết cái gì, cũng chưa biết được cái gì mình chưa biết. Tiến thoái lưỡng nan. Kết quả là bạn sẽ tìm cách quay trở lại cái vòng an toàn và ngủ yên trong đó.

Đó là lý do tại vì sao nhiều người dù có cố gắng vẫn không thể thoát ra khỏi cái vòng an toàn của bản thân.

Giải pháp ở đây là gì?

Không biết.

Có lẽ mỗi người sẽ có một cách khác nhau để vùng vẫy quẫy đạp để có thể bước tiếp ra khỏi vùng lùng bùng, hoặc có khi là chỉ đi quẫy thôi.

Nói về kinh nghiệm bản thân, thực ra mình cũng không biết là mình đã thoát ra khỏi vùng lùng bùng này chưa, mình chọn cách đi lùi, bắt đầu rà soát lại kiến thức của bản thân từ những gì cơ bản nhất, từ đó mình tìm ra vô số lỗ hổng kiến thức và bắt đầu vá víu nó một cách nghiêm túc hơn :v Ít ra phương pháp này cũng giúp mình không bị mất phương hướng khi nằm trong vùng lùng bùng này nữa.

Còn chuyện có đi tiếp đến vùng không an toàn được không thì chắc để dành sau này viết tiếp.

Bài viết gốc được đăng tải tại thefullsnack.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

TypeScript vs JavaScript

TypeScript vs JavaScript

Bài viết được sự cho phép của tác giả Tino Phạm

TypeScript là gì

TypeScript làm một ngôn ngữ lập trình mã nguồn mở được phát triển bởi Microsoft. Cha đẻ của TypeScript là Anders Hejlsberg, một kiến trúc sư trưởng (Lead Architect) của ngôn ngữ C# và là cha đẻ của ngôn ngữ lập trình Delphi và Turbo Pascal.

  7 lý do bạn không nên sử dụng TypeScript
  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java

Typescript khác với JavaScript thế nào

Có thể nói TypeScript là một phiên bản nâng cao của JavaScript vì nó bổ sung những kiểu dữ liệu tĩnh và các lớp hướng đối tượng, đồng thời nó bao gồm luôn các phiên bản ES mới nhất (tùy version của TypeScript).

** ES5 = ECAMScript 5 được release năm 2009
** ES6 = ECAMScript 6 được release năm 2015
** Hiện tại là ES9 = ECAMScript 2018 là phiên bản Javascript mới nhất tính tại thời điểm mình viết bài này.

2. Các file TypeScript có đuôi (phần mở rộng – extension) là *.ts . Trong khi các file JS có đuôi được biết là *.js

3. Code được viết bằng TypeScript sẽ được biên dịch thành JavaScript thuần. Thường thì chúng ta sẽ dùng lệnh tsc để biên dịch vì trong TypeScript có tích hợp sẵn một trình biên dịch được viết bằng TypeScript luôn.

4. Với TypeScript chúng ta có thể khai báo biến với từ khóa: varlet và const. Trong khi var chỉ được dùng trong JS ( hình như từ ES6 trở đi JavaScript cũng dùng được var, let và const)

5. Các biến trong code TypeScript thường được dùng với kiểu dữ liệu rõ ràng hơn trong code JavaScript.

Ví dụ 1: Khai báo biến trong TypeScript

var name: string = "Thang Pham";
var isSingle: bool = true;

Ví dụ 2: Khai báo biến trong JavaScript

var name = "Thang Pham";
var isSingle = true;

6. TypeScript kiểm tra kiểu của các biến khi biên dịch code (compile time) trong khi JS kiểm tra lúc chạy (run time)

Ví dụ 3: TypeScript kiểm tra kiểu dữ liệu

function add(num1: number, num2: number){
    return num1 + num2;
}
add(1, 2); //3
add(1, "hai"); //error

Ví dụ 4: JavaScript kiểm kiểu dữ liệu

function add(num1: number, num2: number){
    return num1 + num2;
}
add(1, 2); //3
add(1, "hai"); //1hai

Xem thêm vị trí tuyển dụng Javascript các công ty lớn tại đây

Tại sao viết code dùng Typescript thay vì dùng Javascript

  • TypeScript được sử dụng để code Front-end như Angular 2 (và các phiên bản về sau), React, Ionic,… và back-end như NodeJs.
  • TypeScript hỗ trợ đầy đủ các tính năng mà JavaScript có với các phiên bản JavaScript mới nhất (ECMAScript versions) vì như mình đã nói nó được xem như là một bản nâng cao của JS.
  • Bạn có thể code với JS thì với qua TypeScript cũng như vậy. Vì dù sao thì code TypeScript cũng sẽ được biên dịch lại thành JS mà.
  • TypeScript giúp bạn viết code theo phong cách OOP như: C#, Java. Nghĩa là nó có: class, abstract class, interface, encapsulation, ….
  • Dễ dàng hơn để phát triển các dự án lớn vì nó giúp bạn kiến trúc hệ thống theo Module, namespace.
  • Bạn sẽ dễ dàng code TypeScript khi mà nó được tích hợp trong rất nhiều IDEs như: Visual Studio Code, Sublime Text,…

Đó là những gì mình hiểu về TypeScript. Hy vọng giúp được anh em đang tìm hiểu về TypeScript có được kiến thức nền tảng.

Hãy cho mình biết ý kiến bằng cách comment bên dưới nhé.

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

 

Xem thêm Việc làm lập trình Typescript hấp dẫn trên TopDev

Tái cấu trúc mã nguồn: Chuẩn hóa mã

Tái cấu trúc mã nguồn: Chuẩn hóa mã
Bài viết được sự cho phép của BBT Tạp chí Lập trình
Chuyển các phương thức về lớp phù hợp hơn.

Việc di chuyển phương thức giữa các lớp là công việc diễn ra thường xuyên trong tái cấu trúc. Việc di chuyển này giúp cho các lớp có kích thước phù hợp hơn, và các lớp ít phụ thuộc vào nhau mà khả năng hợp tác giữa các lớp tốt hơn.

  04 Điều Cần Chú Ý Cho Người Mới Làm Automation Test
  "Code dễ đọc" là như thế nào?

Các bước:

  1. Kiểm tra có nên di chuyển các thuộc tính mà phương thức phải dùng
  2. Kiểm tra xem có khai báo của phương thức ở lớp cha và lớp con
  3. Khai báo phương thức ở lớp đích
  4. Sao chép mã từ lớp nguồn tới lớp đích sao cho phương thức hoạt động được
  5. Biên dịch lớp đích
  6. Xác định tham chiếu phù hợp ở lớp nguồn
  7. Chuyển phương thức ở nguồn gọi tới phương thức của lớp đích
  8. Biên dịch và kiểm thử
  9. Xác định xem có xóa phương thức ở lớp gốc và gọi trực tiếp tới phương thức ở lớp địch
  10. Nếu xóa phương thức ở lớp gốc thì phải thay toàn bộ lời gọi từ phương thức này tới phương thức ở lớp mới
  11. Biên dịch và kiểm thử

Ví dụ:

  1. Ta có lớp Account (tài khoản). Nhưng khi nhiều loại tài khoản và mỗi loại tài khoản có cách tính tiền phí khác nhau, nên ta muôn chuyển hàm _overdraftCharge
    vào lớp AccountType
    [sourcecode language="java"]
    class Account...
       double overdraftCharge() {
           if (_type.isPremium()) {
               double result = 10;
               if (_daysOverdrawn &amp;gt; 7) result += (_daysOverdrawn - 7) * 0.85;
               return result;
           }
           else return _daysOverdrawn * 1.75;
       }
    
       double bankCharge() {
           double result = 4.5;
           if (_daysOverdrawn &amp;gt; 0) result += overdraftCharge();
           return result;
       }
       private AccountType _type;
       private int _daysOverdrawn;
    
    [/sourcecode]
  2. Thuộc tính _daysOverdrawn được dùng ở phương thức là một thuộc tính là của mỗi tài khoản, nên ta không di chuyển thuộc tính.
  3. Trong trường hợp này phương thức không được khai báo ở lớp cha cũng như lớp con.
  4. Khai báo phương thức ở lớp đích và sao chép mã tới lớp đích sao cho phương thức hoạt động được
    [sourcecode language="java"]
    class AccountType...
       double overdraftCharge(int daysOverdrawn) {
           if (isPremium()) {
               double result = 10;
               if (daysOverdrawn &amp;gt; 7) result += (daysOverdrawn - 7) * 0.85;
               return result;
           }
           else return daysOverdrawn * 1.75;
       }
    
    [/sourcecode]
  5. Chuyển phương thức ở nguồn gọi tới phương thức của lớp đích
    [sourcecode language="java"]
    class Account...
       double overdraftCharge() {
           return _type.overdraftCharge(_daysOverdrawn);
    }
    
    [/sourcecode]
  6. Ta xóa phương thức ở lớp gốc và gọi trực tiếp tới phương thức ở lớp đích
    [sourcecode language="java"]
    class AccountType...
       double overdraftCharge(Account account) {
           if (isPremium()) {
               double result = 10;
               if (account.getDaysOverdrawn() &amp;gt; 7)
                  result += (account.getDaysOverdrawn() - 7) * 0.85;
               return result;
           }
           else return account.getDaysOverdrawn() * 1.75;
       }
    
    [/sourcecode]
  7. Biên dịch và kiểm thử
  • Chuyển các trường về lớp phù hợp hơn.

    Nếu một trường (thuộc tính) nên được sử dụng ở một lớp khác phù hợp hơn hoặc khi ta thực hiện việc phân tách lớp thì thực hiện việc di chuyển các trường là điều cần thiết.

    Các bước:

  1. Nếu trường đó là public, ta phải bao gói nó
  2. Biên dịch và kiểm thử
  3. Tạo trường ở có getter và setter ở lớp đích
  4. Biên dịch lớp đích
  5. Xác định cách tham chiếu tới lớp đích
  6. Xóa trường ở lớp nguồn
  7. Thay thế tham chiếu tới lớp nguồn bằng lớp đích.
  8. Biên dịch và kiểm thử

Ví dụ:

Ví dụ ta có lớp Account (tài khoản) và ta muốn chuyển trường _interestRate vào lớp AccountType

[sourcecode language="java"]
Class Account...
   private AccountType _type;
   private double _interestRate;

   double interestForAmount_days (double amount, int days) {
       return _interestRate * amount * days / 365;
   }

[/sourcecode]
  1. Tạo trường ở có getter và setter ở lớp đích
    [sourcecode language="java"]
    class AccountType...
       private double _interestRate;
    
       void setInterestRate (double arg) {
           _interestRate = arg;
       }
    
       double getInterestRate () {
           return _interestRate;
       }
    
    [/sourcecode]
  2. Thay thế tham chiếu tới lớp nguồn bằng lớp đích.
    [sourcecode language="java"]
    private double _interestRate;
    
       double interestForAmount_days (double amount, int days) {
           return _type.getInterestRate() * amount * days / 365;
       }
    
    [/sourcecode]
  3. Biên dịch và kiểm thử
  • Đổi các định danh: Đổi tên phương thức, thuộc tính, lớp để không dài, đủ mô tả ý nghĩa, và phù hợp với chuẩn.

    Các bước:

  1. Kiểm tra xem phương thức có được triển khai ở lớp cha hay lớp con không. Nếu có thì phải thực hiện việc thay đổi này với từng triển khai này
  2. Tạo phương thức với tên muốn đổi và sao chép mã của phương thức nguồn vào
  3. Thay đổi các lời gọi tới phương thức cũ bẳng phương thức mới
  4. Xóa phương thức cũ.
  • Kéo lên (pull up): chuyển một thành phẩn của các lớp con lên cho lớp cha.

    Việc xóa bảo mã lặp là một việc quan trọng. Mặc dù việc mã lặp vẫn hoạt động bình thường, nhưng sẽ khó khăn cho rất nhiều việc như khó bảo trì.

    Các bước:

  1. Kiểm tra xem các phương thức ở các lớp con có nguyên mẫu giống nhau không.
  2. Nếu giống nhau thì sao phương thức từ một lớp con lên lớp cha
  3. Xóa phương thức ở từng lớp con và kiểm thử xem có lỗi gì không tới khi chỉ còn phương thức ở lớp cha.

Ví dụ:

  1. Ví dụ ta có các lớp như Hình 6 và muốn kéo phương thức chargeFor lên lớp cha

Hình 6. Các lớp trước khi thực hiện pull up

  1. Ta sẽ tạo phương thức giống hệt ở lớp con ở lớp Customer ta sẽ có như Hình 7

Hình 7. Lớp sau khi thực hiện pull up

  • Đẩy xuống (push down): Chuyển một thành phần của lớp cha xuống cho lớp con. Khi phương thức hoặc thuộc tính chỉ có ý nghĩa ở một lớp con cụ thể mà không phải tất cả. Khi đó thực hiện việc push down là cần thiết

    Các bước:

  1. Khai báo phương thức ở tất cả các lớp con và sao chép thân từ lớp cha xuống lớp con.
  2. Xóa phương thức ở lớp cha
  3. Xóa các phương thức ở lớp con mà không cần thiết
  4. Biên dịch và kiểm thử

Bài viết gốc được đăng tải tại tapchilaptrinh.vn

Có thể bạn quan tâm:

Xem thêm Việc làm it các ngành hấp dẫn trên TopDev