Home Blog Page 109

Mediator Design Pattern – Collaborate via me

Mediator Design Pattern

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Tiếp tục với chuỗi bài viết về Behaviral Pattern (Pattern hành vi), hôm nay là Mediator Design Pattern. Pattern này cũng khá là dễ nhớ nếu hiểu về concepts. Ngoài ra, nó cũng có đôi điểm tương đồng và đôi khi hay bị nhầm lẫn với Observer Pattern.

  30 tiện ích Chrome cho designer và dev
  5 ứng dụng Android tuyệt vời dành cho Android Developer và Designer

Trở thành Guru Design Pattern ngay thôi nào!

1. Mediator Design Pattern là gì?

Mediator Design Pattern is a behavioral design pattern that lets you reduce chaotic dependencies between objects. The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.

Mediator Design Pattern là dạng pattern hành vi, cho phép giảm bớt sự phụ thuộc hỗn loạn giữa các đối tượng. Mẫu này cũng tắt tất cả các giao tiếp giữa object, bắt buộc tất cả các object khi muốn comunication đều phải thông qua đối tượng mediator.

Vì kiểm soát cách thức giao tiếp (communication) giữa các object nên thuộc về behavioral (hành vi). Để dễ nhớ hơn, ta có thể xem Mediator như cảnh sách giao thông thực hiện điều tiết ở ngã tư.

Tuy nhiên điều tiết không chỉ đơn thuần là bấm đèn xanh đỏ, tất cả giao thông qua lại ngã tư đều chịu sự điều khiển của anh cảnh sát này.

Mediator Design Pattern

2. Bài toán thực tế

Phi công và tất cả các phương tiện bay trên trời đều cần được điều khiển. Trong thực tế được biết tới với tên (Đài kiểm soát không lưu).

Mediator Design Pattern

Để tránh xảy ra va chạm, rõ ràng tất cả cá phương tiện bay (máy bay, trực thăng, thủy phi cơ,…) đều phải điện tới Đài kiểm soát không lưu. Với trách nhiệm chính của đài không lưu:

  • Phân luồng bay, đảm bảo không xảy ra va chạm
  • Điều tiết đường băng cho máy bay hạ cánh

Bắt tay thiết kế hệ thống này, ta có thể nghĩ tới ngay Mediator Design Pattern. Đài kiểm soát không lưu lúc này trở thành Mediator.

Quay trở lại với bài toán trong nghề của anh em mình. Giả sử như đang có một cái task khá khoai tạo một dialog với nhiệm vụ edit. Trên dialog có nhiều Button, Checkbox, TextField, Tabs. Một số form trên dialog còn tương tác với element ở form khác. Lúc này, chỉ mỗi cái checkbox thôi cũng có vô vàn relations tới các element khác.

Mediator Design Pattern

Nếu hệ thống phức tạp và có nhiều elements trên màn hình. Lúc này, class implement cho Checkbox, Button thực tất không thể tái sử dụng, không thể sử dụng ở form hay màn hình khác.

3. Giải quyết vấn đề

Rồi, Mediator Design Pattern giải quyết vấn đề nêu trên như thế nào?

Mediator lúc này đúng nghĩa là cảnh sát, quyền uy tối thượng. Mediator sẽ loại bỏ hết tất cả các communication giữa các component. Trường hợp ta muốn component A độc lập với các component khác, mediator sẽ xóa tất cả các liên kết tới A.

Sau khi đã xóa, Mediator Object đóng vai trò như người trung gian, tất cả giao tiếp đều phải thông qua Mediator Object.

Mediator Design Pattern

Các element trên UI lúc này phải giao tiếp gián tiếp với nhau thông qua Mediator Object, không được communication trực tiếp nữa. Về cấu trúc, Mediator Design Pattern bao gồm những thành phần như sau:

Mediator Design Pattern
  • Components là các class bao gồm một số logic xử lí business. Tất cả các component đều sẽ reference tới Mediator Interface, khai báo kiểu của mediator interface. Do implement interface nên có thể tái sử dụng component trong chương trình khác bằng cách link tới Mediator mới.
  • Mediator Interface khai báo những method phục vụ giao tiếp với components, thường bao gồm một method (notification method).
  • ConcreteMediator đóng gói tất cả các relation giữa các component lại với nhau. Giữ tham chiếu tới tất cả component, đôi khi còn quản lý vòng đời của component

Với thiết kế này, Component không bao giờ liên lạc trực tiếp với component khác. Nếu muốn, Component A có thể gửi notify tới Mediator. Lúc Mediator nhận được thông báo, nó sẽ định dạng được thằng component nào đang gọi.

Components should store a reference to the mediator object. The connection is usually established in the component’s constructor, where a mediator object is passed as anargument.

Components nên lưu trữ tham chiếu tới mediator object. Kết nối này thường được thiết lập trong component constructor, mediator object lúc này được truyền tới như là tham số

Ví dụ về Mediator:

Java

import javax.swing.*;

/**
* Common mediator interface.
*/
public interface Mediator {
void addNewNote(Note note);
void deleteNote();
void getInfoFromList(Note note);
void saveChanges();
void markNote();
void clear();
void sendToFilter(ListModel listModel);
void setElementsList(ListModel list);
void registerComponent(Component component);
void hideElements(boolean flag);
void createGUI();
}

Khi tất cả action đã đăng kí ở Mediator. Một action được gọi ở Component sẽ giao tiếp thông qua Mediator. Ví dụ dưới đây là action deleteNote().

Java
import javax.swing.*;
import java.awt.event.ActionEvent;

/**
* EN: Concrete components don't talk with each other. They have only one
* communication channel–sending requests to the mediator.
*
*/
public class DeleteButton extends JButton implements Component {
private Mediator mediator;

public DeleteButton() {
super("Del");
}

@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}

@Override
protected void fireActionPerformed(ActionEvent actionEvent) {
mediator.deleteNote();
}

@Override
public String getName() {
return "DelButton";
}
}

4. Tổng kết

Đầu tiên, nói về ưu điểm:

Mediator đáp ứng được Single Responsibility Principle, communication giữa các component được tổng hợp về một nơi, dễ dàng để quản lý hoặc maintainance sau này. Thứ hai nữa là Open/Closed Principle, trường hợp cần mở rộng, có thể dễ dàng tạo ra mediator mới (không cần phải thay đổi trong component).

Tuy nhiên Mediator Design Pattern lại vẫn có điểm khác so với Observer pattern là gì? – Nhất trụ kình thiên.

The primary goal of Mediator is to eliminate mutual dependencies among a set of system components. Instead, these components become dependent on a single mediator object. The goal of Observer is to establish dynamic one-way connections between objects, where some objects act as subordinates of others.

Mục đích chính cuẩ Mediator là loại bỏ sự phụ thuộc lẫn nhau giữa các components trong hệ thống. Thay vào đó, các component trở nên đọc lập với nhau, giao tiếp thông qua mediator object. Còn mục tiêu của Observers là thiết lập kết nối một chiều giữa objects. Objects này có thể làm ông nội của các objects khác.

Tuy nhiên, nếu implement Mediator theo chiều hướng subscribe và unsubscribe. Các component đăng kí và hủy đăng kí thông qua Mediator object, lúc này, đọc vào chưa chắc là nhận ra được cái khác giữa 2 cha nội này.

5. Tham khảo

Thank for spend the time to read – Have a nice day – Happy coding!

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

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

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

A/B testing và những tiêu chí chính để đánh giá sự thành công của ASO

a/b testing
A/B testing và những tiêu chí chính để đánh giá sự thành công của ASO

ASO hay còn gọi là App Store Optimization – là một hoạt động giúp tối ưu hóa việc hiển thị ứng dụng trên app store. Theo báo cáo của Branch trong Mobile Growth Handbook 2020, 65% users tải app thông qua việc tìm kiếm trên app store, vì vậy nên ASO trở thành một trong những yếu tố quan trọng hàng đầu khi thực hiện Mobile Marketing. App càng được nhiều người nhìn thấy thì việc tìm kiếm cũng trở nên thuận tiện hơn và họ dễ dàng tải app về sử dụng.

Việc làm mobile app lương cao

Mục tiêu của ASO là gì?

ASO ảnh hưởng thế nào đến sự tăng trưởng của ứng dụng?

Trước tiên, ASO đòi hỏi phải tăng khả năng được nhìn thấy của ứng dụng trên Appstore. Cơ hội nhìn thấy càng nhiều thì app sẽ càng được cài đặt nhiều hơn. Càng nhiều user cài đặt thì cơ hội kiếm tiền của công ty sẽ càng cao hơn. Chưa kể khi làm tốt phần ASO thì giá trị và chi phí để tìm một user mới sẽ giảm đi, từ đó lợi nhuận sẽ còn tăng lên cao hơn. Đó là cách ASO ảnh hưởng một cách tích cực đến sự tăng trưởng ứng dụng.

Các tiêu chí đánh giá sự thành công của ASO

Hiện tại đang có khá nhiều cách để đánh giá vấn đề này, tuy nhiên có 2 yếu tố mấu chốt mà bạn không thể bỏ qua đó là Impression và Conversion.

Vậy Impression của app đến từ đâu? Có 4 cách chính để tăng impression cho app: feature, app ranking, keyword ranking và advertising. Trong khi đó Conversion được đánh giá bằng việc install với ASO. Có 2 điểm cần chú ý với conversion là CTR (click to rate) or TTR (tap to rate), đây là tỉ lệ user nhìn thấy được ứng dụng và click vào. Tỉ lệ thứ 2 cần quan tâm là conversion rate, sau khi click vào thì bao nhiêu % user quyết định install app.

Vậy tại sao 2 yếu tố này quan trọng trong việc đánh giá sự thành công của ASO?

Vì nếu tìm mọi cách để tăng impression bao gồm việc chạy ads, dùng các thủ thuật để tăng ranking cho keyword, cho app, trong khi đó chất lượng không thật sự tốt, traffic không cao vì users không thật sự mong muốn tải ứng dụng, sẽ dẫn đến việc dù đổ vào rất nhiều impression nhưng Conversion Rate thấp nên không có thêm được nhiều user.

Đó là lý do vì sao impression và conversion rate là 2 metrics phải luôn song hành với nhau. Làm tốt cả 2 yếu tố này chính là bạn đang làm tốt chiến lược ASO của mình.

Vậy những yếu tố nào ảnh hưởng đến Impression?

  • App feature: Đây có lẽ là mối quan tâm hàng đầu của rất nhiều dev, đó là mong app mình build được feature bởi các editor từ Apple hoặc Google Play. Khi feature sẽ có được rất nhiều lợi ích.

Thứ nhất, app sẽ được promote không tốn tiền trên app store, thậm chí là được nhìn thấy ở những vị trí đắt giá nhất app store. Nhờ thế sẽ có được impression miễn phí rất lớn. Tuy nhiên không phải lúc nào impression cũng mang lại kết quả tốt đẹp. Đôi khi đó không phải là user đang thật sự muốn tìm kiếm ứng dụng mà tải về. Có rất nhiều user tải app về chỉ vì tò mò, không có mục đích sử dụng nên không thể trở thành loyal user mà rất nhanh sẽ uninstall app.

Hoặc thậm chí impression đổ về rất nhiều nhưng lượng cài đặt lại không bao nhiêu. Do đó khi đánh giá bất cứ ASO nào cũng cần dựa trên 2 tiêu chí là impression và conversion.

  • App ranking: Vị trí ranking của app trên các category hay top charts càng cao thì càng được users tìm thấy dễ dàng hơn.
  • Keyword ranking: Đây được xem là yếu tố then chốt quyết định performance tốt nhất trong ASO. Vì keyword là những từ mà user có chủ đích tìm kiếm để tải app nên nếu app ở thứ hạng cao thì vừa được tìm thấy, vừa được tải bởi các user có quality tốt. Điều đó giúp cơ hội họ ở lại nhiều hơn và sử dụng app lâu hơn, trở thành 1 loyal user.

Ở Vulcan Labs, một keyword sẽ được xác định dựa trên 3 yếu tố: Thứ nhất là search volume xem keyword đó có nhiều người tìm hay không, có nhiều ứng dụng đang sử dụng keyword này hay không và keyword này có liên quan gì đến ứng dụng của mình hay không. Vì nếu không đảm bảo 3 yếu tố này mà sử dụng nó trong meta data như app name, subtitle,… sẽ dẫn đến hiện tượng có impression nhưng không có conversion. Keyword có search volume cao chưa chắc đã có sự liên quan đến app bạn đang build.

  Automation testing: Một số công cụ hữu ích cho tester
  Chrome: Giả lập mạng internet chậm lại trong testing

Tầm quan trọng của keyword ranking

Theo báo cáo Share of Voice by Keyword Ranking của Apple, nếu keyword đạt rank số 1 thì có thể chiếm đến 60% share voice, vị trí thứ 2 khoảng 20%, vị trí thứ 3 và thứ 4 khoảng 10%. Nếu nằm ngoài top 5 thì đôi khi sẽ không có bất cứ % nào trong share of voice cho impression và organic install. Đây là kết quả với iOS store.

Còn đối với Google Play, theo mình được biết nếu nằm ngoài top 10 thì gần như không tìm được impression share nào cho keyword.

  • Advertising: Thông thường tiêu chí này không được nhắc đến nhiều trong ASO vì nhiều người quan niệm rằng làm ASO là miễn phí, là thứ mình tự làm nên không đặt advertising vào một trong những yếu tố ảnh hưởng đến ASO. Tuy nhiên đây lại là một tiêu chí quan trọng ảnh hưởng đến hoạt động ASO của bạn. Vì chạy ads sẽ mang về nhiều traffic hơn cho store. Khi có nhiều traffic hơn, nhiều install hơn thì dĩ nhiên cũng sẽ có được ranking tốt hơn trong kết quả tìm kiếm, nên vô hình chung nó còn giúp tăng organic install.

A/B testing cho ASO

A/B testing là gì?

Đó là phương thức đánh giá từ hai hoặc nhiều lựa chọn để so sánh xem lựa chọn nào sẽ mang lại kết quả tốt hơn. Khi áp dụng hình thức A/B testing cho ASO chính là đang test những giá trị khác nhau của các thành phần trên product page để tăng đồng thời 2 yếu tố lượt hiển thị và tỉ lệ chuyển đổi cho ứng dụng.

AB testing là phương thức đánh giá
AB testing là phương thức đánh giá

A/B testing cho ASO với các ứng dụng trên Google Play Store

Google Play Store cung cấp phương thức testing miễn phí là Google Play Store Listing Experiment. Ở đây có thể test rất nhiều các thành phần như app name, icon, screenshot, description, có thể tùy biến testing một cách dễ dàng. Mỗi lần chỉ test 1 tiêu chí để nhận diện được trị nào đang ảnh hưởng đến conversion rate.

Bên cạnh đó, bạn nên tạo ra nhiều tổ hợp để test càng nhiều càng tốt, khi đó kết quả cũng được tối ưu nhất. Không có câu trả lời chính xác cho việc cần phải test bao lâu và mẫu số bao nhiêu cho từng loại ứng dụng. Nhưng nếu testing trong khoảng 1 tuần và thấy rằng sự khác biệt giữa 2 options không nhiều nghĩa là bạn đang cần một mẫu số lớn hơn.

A/B testing cho ASO với các ứng dụng trên iOS

Với iOS, hiện tại không có cách test miễn phí cho A/B testing. Mọi người có thể sử dụng dịch vụ A/B testing của Splitmetric cho iOS app. Dịch vụ này tạo ra những product pages giống hoàn toàn với pages mà chúng ta đang có trên Apple Store và dùng tiêu chí quyết định kết quả tốt nhất là conversion rate.

Cách thứ 2 là Apple Search Ads Creative Set Test: Để hiện hình thức này, khi submit version mới để test sẽ cần upload cả 2 version lên store. Sau đó, những creative cần test đã available, các bạn vào Apple Search Ads platform để tạo 1 campaign mới và set options mình mong muốn ở Asset Selection. Khi đó việc chạy quảng cáo sẽ được thay phiên giữa option default và option cần test. Chúng ta có thể xem report để xem option nào có nhiều impression và conversion rate hơn.

Có một lời khuyên ở Splitmetric mình cảm thấy khá hợp lí đó là các bạn sẽ phải làm gì nếu sự chênh lệch conversion rate giữa 2 options không quá cao? Theo Splitmetric, tất cả những chênh lệch nào dưới 1% thì không thể xem là thắng thế tuyệt đối của một option. Sự khác biệt conversion rate từ 1 – 2% rất dễ dẫn đến việc khi test trên một mẫu số nhỏ thì option đó thắng thế nhưng khi lên đến một mẫu số lớn, được apply cho all users thì gặp hiện tượng performance negative ngược lại, không mang lại sự tăng trưởng như mong muốn. Do đó kết quả testing nào cho sự khác biệt lớn hơn 2% sẽ đáng tin tưởng hơn.

Testing Flow

Để bắt đầu A/B testing thì bạn không thể nào bỏ qua bước đầu tiên là research – nghiên cứu. Thứ nhất nghiên cứu và đối thủ, thị trường và các hình thức chạy hiệu quả nhất đã có. Sau đó cần xem lại dữ liệu người dùng của ứng dụng để nghiên cứu hành vi người dùng trước đi đặt ra giả thuyết để tiến hành thiết kế lựa chọn cho A/B testing

Đối với dụng Camera translator, sau khi nghiên cứu thấy cần cải thiện ASO cho khu vực Nhật Bản, Vulcan Labs đã bắt đầu khảo sát ứng dụng ở Japan Store nằm ở top chart hoặc top category và tìm ra điểm khác biệt về thị hiếu của người dùng ở thị trường này. Người Nhật như có khuynh hướng tải các ứng dụng có screenshot có hơi thẩm mỹ cao hơn là chỉ thể hiện tính năng app một cách trực quan sinh động. Kết hợp với tìm hiểu trong dữ liệu về hành vi người dùng của ứng dụng Camera Translator ở Nhật, team nhận thấy sử dụng chính trong ứng dụng của Nhật thường được dịch sang tiếng Trung hoặc tiếng Hàn.

Với các lý do đó, Vulcan Labs đưa ra các giải pháp:

  • Thiết kế lại screenshot ở một layout khác, chỉ sử dụng một màu nền, hướng đến phương châm đơn giản vẫn là đẹp nhất.
  • Có các hình ảnh demo bằng tiếng Trung to hơn trong screenshot.

Mong muốn của team về kết quả test:

  • Layout sẽ đóng vai trò quan trọng như thế nào đối với screenshot ở thị trường Nhật Bản.
  • Dùng background nhiều màu hay một màu sẽ thu hút hơn.

Kết quả cuối cùng là version cải tiến dùng background thiết kế nghệ thuật hơn và có hình m hoạ tiếng Trung đạt kết quả tốt hơn khi tăng trưởng hơn 2.3% conversion rate và 22.5% organic install cho ứng dụng Camera translator tại thị trường Nhật Bản.

Đại dịch Covid-19 và những thách thức tác động đến ASO trong năm 2020

Báo cáo của Branch 2020 cho thấy có sự thay đổi trong hành vi của người tiêu dùng. Trước đây, việc tải ứng dụng đa phần đến từ việc user nhìn thấy quảng cáo và cảm thấy hứng thú nhiều hơn việc họ tự tìm kiếm một ứng dụng và chủ động tải.

Đến giai đoạn dịch Covid-19, việc tìm kiếm ứng dụng trở thành nhu cầu thiết yếu hơn. Đa số người dùng sẽ lên app store và chủ động tìm kiếm những ứng dụng phù hợp với nhu cầu của mình như để giải trí, cập nhật tin tức hoặc để giao tiếp với bên ngoài.

  Làm thế nào để chọn được framework phát triển Mobile app tốt nhất?

Vậy sự dịch chuyển này tác động như thế nào đến ASO?

Traffic đến từ việc users search keyword sẽ tác động đến keyword ranking nên khi keyword có traffic search volume rất lớn sẽ trở thành mục tiêu mà nhiều competitor hướng đến và trở thành một “trận chiến”.

Trước đây việc chạy ads có thể hỗ trợ một phần cho ASO thì hiện giờ vai trò của ads trong hỗ trợ tăng thêm impression trở nên nhỏ hơn. Vì vậy việc tối ưu hoá tất cả các yếu tố có trên product page để khiến người dùng tải app trở thành yếu tố quan trọng hơn nữa trong việc thực hiện thành công ASO. Lúc này, vai trò của ASO sẽ ngày càng nhiều hơn và đóng góp mạnh mẽ hơn cho sự thành công trong việc tìm kiếm users mới cũng như sự tăng trưởng cho ứng dụng.

Bài viết được trích dẫn từ phần trình bày của Ms Châu Lê tại sự kiện Vietnam Mobile Day 2020 LIVE do TopDev tổ chức


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

Xem thêm các việc làm it hấp dẫn tại TopDev

Những điều cần lưu ý khi dùng git để quản lý source code

Những điều cần lưu ý khi dùng git để quản lý source code

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

Sau một vài buổi trao đổi với các bạn làm quen với GIT mình tổng hợp một số quan điểm và những điều cần lưu ý khi dùng GIT mà các bạn này hay thắc mắc. Bài này chỉ thích hợp cho mấy bạn đã nắm qua git cơ bản rồi mà chưa có đụng chạm các vấn đề thực tiễn nhiều nhé!

  10 Vấn đề về Git thường gặp và Giải pháp
  5 tip về GitHub cho lập trình viên
  • Lúc commit rồi mà phát hiện ra commit đó sai quá sai thì phải undo hay xóa cái commit đó ra sao?
  • Muốn quay lại commit thứ N thì làm sao? 

Thông thường và dể dùng nhất là dùng git reset tuy nhiên còn vài cách khác dễ dùng hơn nửa đấy!

Bạn có thể tham khảo tại bài này -> Giới thiệu 3 cách undo commit hoặc loại bỏ commit cơ bản


  • Tôi đang chưa hiểu rõ sự khác biệt giữa git merge và git rebase là gì?
  • Tại sao tôi lại dùng git rebase mà không phải merge trong dự án này?
  • git rebase nó hay bị nhiều conflict hơn git merge?
  • git merge dễ tra log hơn git rebase đúng không vì rebase sửa log lại hết rồi 😐 ?

Lý do áp dụng rebase trong dự án là cho mọi thứ đều dễ dàng xem, điều tra log khi xem qua transport plan trong git. Chính vì thế việc áp dụng rebase cho từng brach riêng biệt là cách để cac developer có tư duy logic tốt log một cách có hệ thống những commit thực sự quan trọng và cần thiết để tra cứu sau này hạn chế commit spam ngoài ý muốn.

Việc conflict trong git là điều không thể tránh khỏi khi merge hay rebase branch khác mà làm chung trên 1 file mình chưa thấy dẫn chứng nào là rebase conflict nhiều hơn merge.

Bạn muôn biết rõ sự khác biệt này thì vào xem bài viết này -> Sự khác biệt giữa git merge và git rebase


  • Trước khi commit mới thì mình phải pull code mới về, mà nếu gặp conflict thì phải xử lý, nếu xử lý ko khéo thì mất code của mình làm, vậy phải làm sao đây?
  • Nếu chỉ backup 1 lần cho 1 commit thì cực quá vì pull nhiều branch thì sao?
  • Mình đang làm branch hiện tại chưa muốn commit, mà phải qua branch khác fix bug dùm member vậy thì phải làm sao?

Nhìn chung mọi câu hỏi đều xoay quanh việc bạn muốn backup code mà chưa thể commit được! Có 1 câu thần chú mà mình hay dùng đó là git stash nó cho phép bạn backup mọi lúc, không giới hạn số lần backtup và bạn dễ dàng tra cứu lại những gì bạn backup nữa.

Bạn muôn biết rõ sự khác biệt này thì vào xem bài viết này -> Tổng hợp sử dụng git stash hiệu quả

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

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

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

Dùng MicroPython với wifi board ESP-8266

Dùng MicroPython với wifi board ESP-8266

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

Khi trở thành một trong những ngôn ngữ lập trình phổ biến nhất thế giới, Python không chỉ được dùng trong làm web, data science, hay sysadmin tool mà nó còn đá sang cả một lĩnh vực vốn giới hạn về tài nguyên: nhúng.

Bình thường khi bật Python lên để in ra màn hình dòng “hello, world” ta đã dùng tới 8MB bộ nhớ. Vậy nên việc dùng Python cho lập trình nhúng thường nghe có vẻ không phù hợp.

MicroPython ra đời, là một bản thu gọn của Python, tối ưu chạy trên các vi xử lý cũng như các môi trường giới hạn về tài nguyên. Bài này khám phá việc chạy MicroPython trên một thiết bị tí hon có tên WEMOS D1 mini.

WEMOS D1 mini

Là 1 bảng mạch điện có khả năng thu phát sóng wifi (wifi board) có kích thước nhỏ hơn ngón chân cái của người lớn, thiết bị này có giá 2 USD.

WEMOS D1 Mini

Bảng mạch này sử dụng vi điều khiển (microcontroller) ESP-8266, với xung nhịp 80MHz/160MHz, 96KB RAM và 4 MB Flash.

Microcontroller

A microcontroller is a small computer on a single integrated circuit. In modern terminology, it is similar to, but less sophisticated than, a system on a chip or SoC; an SoC may include a microcontroller as one of its components. A microcontroller contains one or more CPUs along with memory and programmable input/output peripherals.

Một vi điều khiển là một máy tính nhỏ, trên một mạch điện tử (P/S: SoC là khái niệm tương tự, nhưng phức tạp hơn). Nó có một hoặc nhiều CPU, memory và chỗ để thực hiện vào ra dữ liệu.

Hãy nhìn vào chiếc máy bàn hay laptop bạn đang dùng, nó có 1 cục CPU to bằng lòng bàn tay, vài thanh RAM dài như bàn tay, các cổng vào ra đều to bằng ngón tay. Mỗi cục CPU đều từ 2-3 GHz (so với 80MHz), ổ cứng vài trăm GB (so với 4MB), 1-16 GB RAM (so với 96KB RAM). Ta sẽ thấy microcontroller nhỏ bé và “yếu ớt” đến chừng nào.

WEMOS D1 Mini

MicroPython

Phiên bản Python dành riêng cho các thiết bị tí hon này nhỏ tới mức chỉ cần 256kB không gian chứa code, và 16kB RAM.

  Hướng dẫn lập trình Python trên Eclipse với plugin PyDev

Cài đặt MicroPython lên WEMOS D1 Mini trên Ubuntu 16.04

(Windows hay OSX cần cài driver, hãy lên trang chủ của WEMOS để tải và xem hướng dẫn).

Cắm thiết bị vào máy tính sử dụng dây micro USB (dây sạc điện thoại android), sẽ thấy nháy đèn trên thiết bị, gõ lệnh dmesg để xem Linux kernel báo nhận thiết bị:

$ dmesg
...
[  992.253009] usb 2-1: new full-speed USB device number 5 using xhci_hcd
[  992.402181] usb 2-1: New USB device found, idVendor=1a86, idProduct=7523
[  992.402185] usb 2-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  992.402187] usb 2-1: Product: USB2.0-Serial
[  992.402757] ch341 2-1:1.0: ch341-uart converter detected
[  992.403119] usb 2-1: ch341-uart converter now attached to ttyUSB0
$ file /dev/ttyUSB0
/dev/ttyUSB0: character special (188/0)

Ta có thấy xuất hiện 1 file mới gọi là /dev/ttyUSB0, đây chính là thiết bị vừa kết nối.

Cài đặt MicroPython sử dụng esptool

Cài đặt esptool dùng pip:

$ pip install esptool
Collecting esptool
...
Successfully installed ecdsa-0.13 esptool-2.5.1 pyaes-1.6.1 pyserial-3.4

Xóa nội dung hiện tại trong flash memory

$ sudo /home/hvn/py36/bin/esptool.py --port /dev/ttyUSB0 erase_flash
esptool.py v2.5.1
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
MAC: b4:e6:2d:3b:22:1b
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 1.6s
Hard resetting via RTS pin...

Tải MicroPython bản dành cho ESP8266: bản mới nhất tại thời điểm viết bài http://micropython.org/resources/firmware/esp8266-20180511-v1.9.4.bin

Ghi micropython lên flash memory:

$ sudo /home/hvn/py36/bin/esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 ~/esp8266-20180511-v1.9.4.bin
esptool.py v2.5.1
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
MAC: b4:e6:2d:3b:22:1b
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0240
Compressed 604872 bytes to 394893...
Wrote 604872 bytes (394893 compressed) at 0x00000000 in 9.0 seconds (effective 536.4 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

Sau khi cài đặt xong, bấm nút “reset” trên thiết bị để khởi động lại, ngay sau đó bật WIFI của laptop hay điện thoại lên ta sẽ thấy một mạng WIFI có tên MicroPython-xxxxxx, có thể kết nối vào WIFI này với password micropythoN. Ở đây ta không cần làm việc này. Tiếp tục cài đặt để kết nối với thiết bị qua cổng COM:

Cài picocom:

$ sudo apt install -y picocom
$ sudo picocom /dev/ttyUSB0 --baud 115200
picocom v1.7

port is        : /dev/ttyUSB0
flowcontrol    : none
baudrate is    : 115200
parity is      : none
databits are   : 8
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
nolock is      : no
send_cmd is    : sz -vv
receive_cmd is : rz -vv
imap is        :
omap is        :
emap is        : crcrlf,delbs,

Terminal ready

>>> 2**1000
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

Sau khi kết nối, ta lập tức sử dụng Python interpreter như bình thường.

  Chiến trường sinh tử phiên bản lập trình : Python vs Ruby vs Golang

Python interpreter đóng vai trò như 1 hệ điều hành ở đây, mỗi lần reset thiết bị, nó sẽ lại bật lại Python interpreter. Mọi tương tác với thiết bị (đọc/ghi file) đều thực hiện qua code python.

>>> import os
>>> os.getcwd()
    '/'
>>> os.listdir()
['boot.py', 'main.py']

Hai file này được chạy mỗi lần thiết bị khởi động.

Xem nội dung file boot.py:

>>> f = open('boot.py')
>>> print(f.read())
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
    import gc
#import webrepl
#webrepl.start()
    gc.collect()

File main.py chứa code của người dùng muốn chạy mỗi lần bật thiết bị. Ví dụ ta muốn hiển thị dòng hello PyMi:

>>> f = open('main.py', 'wt')
>>> f.write('print("Hello Pymi.vn")')
22
>>> f.close()

Bấm nút reset sẽ thấy:

...
ets_task(40100130, 3, 3fff83ec, 4)
Hello Pymi.vn

MicroPython v1.9.4-8-ga9a3caad0 on 2018-05-11; ESP module with ESP8266
Type "help()" for more information.
>>>

Thao tác với các chân Pin

>>> from machine import Pin
>>> P0 = Pin(0, Pin.OUT)
>>> P0.
__class__       IN              IRQ_FALLING     IRQ_RISING
OPEN_DRAIN      OUT             PULL_UP         init
irq             off             on              value
>>> P0.on()
>>> P0.off()
>>>

Baud

Baud /ˈbɔːd/ ở câu lệnh trên là một độ đo “symbol rate” (symbol per second), để quyết định tốc độ giao tiếp qua một kênh thông tin.

Kết luận

Với MicroPython trên thiết bị, ta đã có thể thực hiện điều khiển các chân Pin hay gửi HTTP request như code Python bình thường. Giờ thì giới hạn chỉ còn là trí tưởng tượng của bạn.

Tham khảo

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

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

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

Các từ khóa/key words trong ngôn ngữ C/C++

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Từ khóa (keyword) trong C

Từ khóa là các từ được định nghĩa sẵn trong ngôn ngữ C, mang một ý nghĩa nào đó. Không thể dùng từ khóa để làm định danh, tên biến hay hằng số.

  50 keywords mà mọi JAVA developer nên biết
  NoSQL Key Value Stores must know

C gồm 32 từ khóa:

auto double int struct
break else long switch
case enum register typedef
char extern return union
const float short unsigned
continue for signed void
default goto sizeof volatile
do if static while

Từ khóa trong C++

Ngoài những từ khóa trong C thì C++ còn bổ sung thêm một số từ khóa khác như

true false private protected public
try catch dynamic_cash reinterpret_cast static_cast
const_cast throw explicit new this
asm operator namespace typeid typename
class friend template using virtual
delete inline mutable wchar_t bool
And bitor not_eq xor and_eq
compl or xor_eq bitand not
or_eq export explicit

Tìm việc làm C++ nhanh chóng trên TopDev

Ngoài ra, C++ vẫn còn một số từ khóa khác được bổ sung các version mới ví dụ:

alignas (since C++11) alignof (since C++11) and
and_eq asm atomic_cancel (TM TS)
atomic_commit (TM TS) atomic_noexcept (TM TS) auto(1)
bitand bitor bool
break case catch
char char16_t (since C++11) char32_t (since C++11)
class(1) compl concept (since C++20)
const constexpr (since C++11) const_cast
continue co_await (coroutines TS) co_return (coroutines TS)
co_yield (coroutines TS) decltype (since C++11) default(1)
delete(1) do double
dynamic_cast else enum
explicit export(1) extern(1)
false float for
friend goto if
import (modules TS) inline(1) int
long module (modules TS) mutable(1)
namespace new noexcept (since C++11)
not not_eq nullptr (since C++11)
operator or or_eq
private protected public
register(2) reinterpret_cast requires (since C++20)
return short signed
sizeof(1) static static_assert (since C++11)
static_cast struct(1) switch
synchronized (TM TS) template this
thread_local (since C++11) throw true
try typedef typeid
typename union unsigned
using(1) virtual void
volatile wchar_t while
                       xor                     xor_eq
Okay, Done!

Rx-MVVM(2): Cấu trúc project – quản lý thư viện sử dụng trong dự án

Rx-MVVM(2): Cấu trúc project – quản lý thư viện sử dụng trong dự án

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

Có thể bạn đã sử dụng nhiều library trong dự án IOS của mình. Vậy thường thì bạn có tạo lớp để quản lý cho dễ không? Thực tế mình cũng ít khi làm việc này, chỉ trừ mấy thư viện lớn như request server thôi. Hôm nay chúng ta sẽ học được 1 cách quản lý thư viện mà theo mình đánh giá là ổn, khá logic, clear và đáng học hỏi. Nào cũng ta cùng bắt đầu nhé!

  6 project vui dành cho dev build khi chán
  9 CSS animation mới "mãn nhãn" cho các project

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

AnalyticsManager

Trong file này tác giả sử dụng 2 thư viện Mixpanel và FirebaseAnalytics.

Thư viện Mixpanel:

https://github.com/mixpanel/mixpanel-iphone

Phần Readme đã mô tả rất rõ cách cài đặt, các bạn đọc và tạo thử 1 project để cài nhé. Mình nghĩ dùng pod để cài là đơn giản nhất.

Chức năng:

  1. Cung cấp event tracking model tốt hơn
  2. Dữ liệu thống kê realtime – thống kê của GA thường mất hàng giờ
  3. Với GA bạn phải tạo ra các funnel trước khi thu thập dữ liệu, còn với Mixpanel bạn có thể xây dựng funnel bất cứ lúc nào.
  4. retention analytics – Cho phép đo lường lượng người dùng mới, sử dụng lại app. Nó cũng cho phép bạn xác định tần suất người dùng sử dụng app, GA không có tính năng này.
  5. Customer support: GA không cung cấp hỗ trợ người dùng chất lượng cao nếu bạn gặp lỗi và không hiểu báo cáo.
  6. Cải thiện độ chính xác dữ liệu
  7. Mobile A/B testing: Mixpanel cung cấp mobile a/b testing, dễ dàng cho người phát triển hoặc không biết kỹ thuật. GA không có chức năng này.
  8. Dữ liệu của bạn được private. Không như GA, Mixpanel không bao giờ sử dụng dữ liệu của bạn cho mục đích quảng cáo.

Các bạn vào đây để đăng ký 1 tài khoản dùng thử:

https://mixpanel.com/

Sau đó đăng ký vào copy key để lưu vào project.

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

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

Sử dụng xlwings tương tác với MS Excel

Sử dụng xlwings tương tác với MS Excel

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

xlwings là 1 thư viện Python dùng để tương tác giữa Python và MS Excel. Hoạt động được trên Windows và Mac. xlwings có các tính năng:

  Checked và Unchecked Exception trong Java
  PHPExcel - Import và Export xử lý Excel
  • Scripting: Tự động hóa/tương tác với Excel từ môi trường Python, sử dụng cú pháp gần với VBA mà vẫn “Pythonic”.
  • Macros: Viết các script python thay thế cho VBA macros, giúp code dễ đọc hơn. Sau khi viết script python xong, chỉ cần gọi 1 hàm trong VBA là script chạy.
  • UDFs: Viết hàm người dùng tự định nghĩa bằng ngôn ngữ Python và sử dụng được hàm đó trong excel (Windows only).
  • REST API: cung cấp REST API cho Excel workbook.

Cài đặt:

pip install xlwings

Sử dụng:

  1. Một số thao tác cơ bản:
import xlwings as xw

# mở workbook mới
new_wb = xw.Book()
# hoặc
opening_wb = xw.Book('name_of_opening_workbook')
# hoặc
open_new_workbook = xw.Book('full/relaive_path_to_xls')

# Lấy các sheets có trong file excel 
xw.sheets

# Làm việc với dữ liệu trong 1 sheet
sht = xw.sheets[0]
print(sht.range('A1').value)
sht.range('A1').value = 'xxx'

# tự động tìm bảng
# https://docs.xlwings.org/en/stable/datastructures.html#range-expanding
sht.range('A1').expand()
# ...

Ngoài ra, xlwings còn tích hợp pandas.

  1. Xử lý trường hợp cụ thể: Trong video này, xlwings được dùng để tự động tạo các named range cho hàng loạt file có cấu trúc tương tự. Mục đích là để làm bước tiếp theo: link giá trị từ nhiều file vào 1 file tổng hợp, dựa vào named range trong từng file chi tiết. Tham khảo script.

Trong script này còn sử dụng Excel VBA API: WorkBook.Names.Add (tra cứu toàn bộ ở đây, được cung cấp qua xw_object.api). Tức là những gì không được cung cấp sẵn cú pháp Pythonic, ta sẽ sử dụng VBA API.

Hạn chế: range expand chỉ ứng dụng được cho vùng dữ liệu liên tục. Với “bảng” có các dòng/cột trống (để “format” cho đẹp) thì sẽ bị ngắt tại chỗ có dòng/cột trống. Vì vậy, thường sẽ phải chọn 1 range khá lớn/1 magic number để lấy được toàn bộ vùng dữ liệu cần xử lý.

Mọi việc phải xử lý trong video demo sẽ đơn giản hơn nếu có 1 file excel mẫu ban đầu, được định nghĩa sẵn các named range, sau đó mới duplicate ra để điền dữ liệu vào. Tuy nhiên, thực tế không như thế, ta phải xử lý lỗi một cách nhanh nhất, cũng giống như khi tập chép phạt: "Anh xin lỗi\n" * 100

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

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

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

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Để build, run các project Java, Spring ta cần cấu hình để cho Jenkins cài đặt Java hoặc sử dụng Java có sẵn trên máy.

  Hướng dẫn build java project, maven project trên Jenkins
  Hướng dẫn deploy Java Project, Maven Project với Jenkins

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Trên thanh Menu bên trái chọn Manage Jenkins > Global Tool Configuration

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Cuộn màn hình xuống dưới sẽ thấy phần Add JDK, Click vào nút Add JDK

Cách 1: Cấu hình JDK cho Jenkins bằng cách download từ trang của oracle

Chọn vào ô check box Install automatically

Với cách này, Jenkins sẽ tự động download bản JDK trên trang oracle về máy và cài đặt. Tất cả sẽ thực hiện tự động, bạn không cần phải cấu hình gì cả.

Tuy nhiên với cách này bạn cần phải có 1 tài khoản oracle, và thêm account oracle đó vào jenkins

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Thêm tài khoản oracle vào Jenkins

Hướng dẫn cấu hình JDK (Java) cho Jenkins Hướng dẫn cấu hình JDK (Java) cho Jenkins

Chọn version JDK muốn cài đặt (ở đây mình dùng JDK 1.8). Đặt tên cho bản JDK (nên đặt giống tên version JDK để dễ nhớ)

Tick vào ô I agree to the Java SE Development Kit License Agreement

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Click nút Save, hệ thống sẽ tự động download Java về máy (Quá trình này chạy ngầm, nên sau khi add JDK bạn có thể chưa build được project Java do nó chưa cài đặt xong)

Cách 2: Cài đặt JDK cho Jenkins bằng Java ở local

Với cách này, yêu cầu máy bạn đã cài đặt Java và cấu hình JAVA_HOME

Để kiểm tra biến JAVA_HOME, mở cửa sổ terminal (Ctrl + Alt + T) và gõ echo $JAVA_HOME

Ví dụ, máy mình đang cài Java ở folder /opt/java/jdk1.8.0_261

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Cấu hình JDK cho Jenkins bằng Java trên local bằng cách bỏ chọn ô checkbox Install automatically

Trường JAVA_HOME nhập và đường dẫn JAVA_HOME mà bạn cấu hình trên máy.

Nhập tên cho bản JDK và click Save

Hướng dẫn cấu hình JDK (Java) cho Jenkins

Với cách này, Jenkins không cần cài đặt gì cả nên sau khi save bạn có thể build, chạy các project Java được luôn.

References: https://www.jenkins.io/doc/

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

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

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

How to Design System like TinyURL – P1

Bài viết được sự cho phép của tác giả Kiên Nguyễn

TinyURL là hệ thống rút gọn link được sử dụng phổ biến trên toàn thế giới. Link dài, link rắc rối, link không muốn người khác nhìn vào là biết?. Tất cả đều được xử lí với TinyURL

Một hệ thống như vậy thông thường sẽ xử lí một lượng lớn request phân giải Short URL thành Original URL. Việc phân giải đòi hỏi chính xác, nhanh chóng.

  10 kênh Youtube học lập trình không thể bỏ qua dành cho Junior Web Developer / Designer
  30 tiện ích Chrome (extensions) cho Designer và Developer

Hôm sau Kieblog sẽ giới thiệu chuỗi bài viết thiết kế hệ thống như TinyURL, bao gồm 2 phần.

  • Phần 1: Tổng quan hệ thống, đưa ra giải pháp thiết kế
  • Phần 2: Thiết kế chi tiết, giải quyết các vấn đề thực tế

Bắt đầu ngay thôi nào!

1. Về TinyURL System

Bản thân Tiny URL là hệ thống rút gọn link. Trường hợp link quá dài, loằng ngoằng không hồi kết, để rút gọn link cho dễ thao tác và sử dụng ta có thể sử dụng Tiny URL.

Về mặt bản chất, Tiny URL thực chất là hệ thống implementing a distributed key-value store. Hiện thực hệ thống phân tán, lưu trữ theo cơ chế key-value.

How to Design System like TinyURL – P1

Key ở đây được hiểu là short url đã rút gọn. Value là original url trước khi rút gọn.

Java

makeTinyURL("http://www.yahoo.com?search=what+is+hello+world") = ksfskfh
makeTinyURL("http://www.google.com/mail?id=dsbsj234-3rfwd-3e3r..") = djhdhsf

Thông qua function makeTinyURL, ta có thể lấy được URL lưu trữ trong hệ cơ sở dữ liệu phân tán (Distributed System).

Key -> Value

The user can now share tinyurl.com/ksfskfh. Whenever someone visits that URL, our system will look up the Distributed Database and redirect them to the actual URL.

Về cơ bản, sau khi đã rút gọn, user có thể chia sẻ short URL. Bất cứ ai khi đi tới short URL, hệ thống sẽ tìm kiếm trong Hệ cơ sở dữ liệu phân tán và chuyển hướng người dùng tới URL chính xác.

2. Bắt tay vào thiết kế hệ thống

Do việc lấy original URL được thực hiện ở phía Server, tất nhiên ta sẽ cần một App Server để xử lý. Về phía Database, ta sẽ sử dụng Sharing Distributed, do lượng người sử dụng và số lượng URL shorted rất lớn.

Trung bình có thể tới vài triệu URL được rút gọn trong vòng một ngày. Việc lưu trữ ở phía DB đòi hỏi áp dụng thiết kế Sharding, lưu trữ phân tán.

Chi tiết thêm về Dynamic Sharding anh em có thể tham khảo thêm ở bài viết này

Chi tiết hệ thống có thể được thiết kế như hình vẽ sau đây

How to Design System like TinyURL – P1
  • CDN (Content Delivery Network) hỗ trợ cache, tăng performance cho system.
  • Load Balancer giúp cân bằng tải, handle một lượng lớn request extract URL hàng ngày. Lượng request yêu cầu extract URL có thể lên tới hàng trăm ngàn request mỗi giây
  • App Server thực hiện Original URL (URL gốc) từ Database thông qua tìm kiếm key-value ở Database.
  • Distributed Database là hệ thống cơ sở dữ liệu phân tán, scale theo chiều ngang giúp mở rộng hệ thống, đáp ứng perfomance khi lượng request lớn.

3. Bài toán mà hệ thống cần giải quyết

Đi sâu hơn vào chi tiết, hệ thống như Tiny URL đặt ra nhiều câu hỏi cho người thiết kế hệ thống.

Cụ thể, bản thân người kĩ sử sẽ cần xem xét

1. What method do we use to generate the shortened URL?

Method nào sẽ sử dụng để tạo các URL ngắn. Chuỗi phía sau URL sẽ được tạo ra như thế nào để đảm bảo tính duy nhất (unique). Dễ dàng cho việc tìm kiếm?.

2. How long should the shortened URL be?

URL được làm ngắn sẽ trông như thế nào?. Tất nhiên, đã là rút gọn link thì sau khi rút gọn phải ngắn hơn, chứ mà sau khi rút gọn còn dài hơn cả trước khi rút gọn thì hệ thống FAIL. LOL

3. What happens if the same URL is shortened twice? Do we re-use the old TinyURL or create a new one?

Trường hợp URL đã được rút ngắn, chuyện gì xảy ra khi rút thêm lần nữa?. Ngắn hơn?. Có nên sử dụng cái TinyURL đã thiết kế, hay tạo ra cái mới?.

Tất cả các câu hỏi này cần bản thân người kĩ sư tìm ra câu trả lời. Một phán đoán sai hay giải pháp không tốt có thể ảnh hưởng tới toàn bộ hệ thống. Chính vì vậy, các vấn đề kĩ thuật cần được giải quyết triệt để.

Đón đọc tiếp bài viết thứ hai. How to Design System like TinyURL – part 2

4. Tham khảo

Cảm ơn vì đã đọc bài – Have a great day

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

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

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

RxSwift 1: Xin chào RxSwift!

RxSwift 1: Xin chào RxSwift!

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

Dựa theo tác giả: Marin Todorov.

Loạt bài đăng này giới thiệu cho bạn cách viết ứng dụng IOS sử dụng Reactive bằng ngôn ngữ Swift. Vậy chính xác RxSwift = Reactive + swift là gì?

  • Nó là thư viện để xử lý các sự kiện không đồng bộ (theo thời gian thực) nhờ việc tạo ra các observable quan sát và các toán tử (operators) chức năng xử lý tham số hóa nhờ schedulers – lập lịch.
  • Nói nôm na, ví dụ người yêu bạn thấy trời nắng thì liền dùng ô, thấy mưa thì chạy vào nhà. Sự kiện mưa nắng là ngẫu nhiên, nhưng việc xử lý chính xác dùng ô hay chạy vào nhà gọi là schedulers. Các observable chính xác là mắt nhìn của người yêu bạn. Trong lập trình reactive nó cũng tương tự như vậy.
  RxSwift 10: Làm việc với PublishSubjects
  RxSwift 3: Thuật ngữ về lập trình bất đồng bộ (Asynchronous programming glossary)

Đọc cũng phức tạp, vì nó còn mới. Nhưng chúng ta hãy đi từ từ từng khái niệm một nhé.

Mục tiêu của loạt bài chủ đề này: Học cách sử dụng các hàm của RxSwift – hay còn gọi là APIs của nó, và áp dụng được nó vào ứng dụng IOS của bạn. Chúng ta sẽ học những API cơ bản, và sau đó nâng dần lên trung cấp và nâng cao. Hãy giành thời gian thực hành theo các ví dụ và vì Reactive là 1 khái niệm rất rộng cho nên khó có thể viết hết về nó được. Nhưng chúng tôi hi vọng qua loạt bài này sẽ cung cấp cho các bạn các kiến thức căn bản đủ để bạn tiếp tục theo đuổi nó và nâng dần trình độ của mình lên. Chúng ta sẽ không lo nó lỗi thời, vì hiện tại Apple đã cung cấp Combine, 1 framework chính chủ cũng áp dụng y hệt cách hoạt động của RxSwift, chúng ta có thể dễ dàng di chuyển qua nó. Thông qua Rx, chúng ta có thể đọc code bằng các ngôn ngữ khác viết cho android hay web.

Tuy nhiên chúng ta vẫn chưa biết Rx là gì phải không? Vậy hãy bắt đầu bằng 1 định nghĩa đơn giản dễ hiểu sau:

Về bản chất, RxSwift đơn giản hóa việc phát triển các chương trình không đồng bộ bằng việc cho phép ứng dụng của bạn phản ứng các thay đổi của dữ liệu mới theo cách riêng biệt, tuần tự.

Là một nhà phát triển ứng dụng IOS, điều này là dễ hiểu hơn nhiều so với khái niệm ở trên, ngay cả khi mơ hồ thì bạn cũng hiểu là Rx giúp bạn viết mã cho các chương trình bất đồng bộ. Và mọi việc hỗ trợ cho việc viết code bất đồng bộ dễ hiểu, trong sáng(clean) đều được hoan nghênh. Vì vậy chúng ta còn chần chừ gì mà không đọc tiếp bài 2 ở đây.

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

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

Xem thêm: Tìm việc làm swift hấp dẫn trên TopDev

C thật là đơn giản

C thật là đơn giản

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

Đơn giản, nhanh, chậm, xinh, cao, thấp, giỏi, xịn… đều là những khái niệm mang tính chất tương đối. Có cái hơn khi so sánh ở góc độ này, nhưng lại kém khi so sánh ở góc độ khác. Trong ngành lập trình, mọi thứ đều là sự đánh đổi (trade off), không có giải pháp nào thỏa mãn tất cả mọi nhu cầu (silver bullet) – hoặc có nhưng chưa ai tìm ra.

Không cần bàn cãi, ai cũng đồng ý code Python dễ đọc, viết hơn C, hay… đơn giản hơn. Nhưng cái đơn giản đó, là đơn giản với con người, với lập trình viên, còn với máy tính thì hoàn toàn ngược lại.

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

Ta sẽ thử nghiệm chương trình đơn giản nhất trái đất: hello world viết bằng C và Python rồi so sánh dùng strace – một công cụ debug “cao cấp” thường dùng bởi các SysAdmin.

strace

$ whatis strace
strace (1)           - trace system calls and signals

Bài viết thực hiện trên Ubuntu 18.04, cc – C compiler có lẽ là có sẵn. Hoặc nếu không có, hãy cài bằng sudo apt-get install -y build-essential strace

C Programming language

4 dòng code C

#include <stdio.h>

int main(void) {
    puts("Hello world!");
}

Compile rồi chạy – yeah, cực đơn giản, không cần gì khác cả, cũng không cần làm việc đơn giản này trở thành rắc rôi.

$ cc hello.c -o hello  # compile, sinh ra file hello
$ ./hello  # chạy file hello
Hello world!

Giờ chạy với strace để xem chương trình siêu đơn giản này gọi những system call nào, -C sẽ hiển thị bảng thống kê, -S calls sẽ sắp xếp thống kê này theo cột calls, giảm dần.

$ strace -CScalls ./hello
execve("./hello", ["./hello"], 0x7fff1e9af718 /* 68 vars */) = 0
brk(NULL)                               = 0x56174aa4e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106420, ...}) = 0
mmap(NULL, 106420, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f867f8fc000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f867f8fa000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f867f2fe000
mprotect(0x7f867f4e5000, 2097152, PROT_NONE) = 0
mmap(0x7f867f6e5000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f867f6e5000
mmap(0x7f867f6eb000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f867f6eb000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f867f8fb4c0) = 0
mprotect(0x7f867f6e5000, 16384, PROT_READ) = 0
mprotect(0x56174a941000, 4096, PROT_READ) = 0
mprotect(0x7f867f916000, 4096, PROT_READ) = 0
munmap(0x7f867f8fc000, 106420)          = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 5), ...}) = 0
brk(NULL)                               = 0x56174aa4e000
brk(0x56174aa6f000)                     = 0x56174aa6f000
write(1, "Hello world!\n", 13Hello world!
     )          = 13
exit_group(0)                           = ?
+++ exited with 0 +++
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         5           mmap
  0.00    0.000000           0         4           mprotect
  0.00    0.000000           0         3           fstat
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         3         3 access
  0.00    0.000000           0         2           close
  0.00    0.000000           0         2           openat
  0.00    0.000000           0         1           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    27         3 total

Có tổng cộng 27 syscall được thực hiện, 3 fail.

Python

Một chương trình Python 3.6 in ra màn hình dòng chữ hello world tương tự:

$ strace -cScalls python3 -c 'print("Hello world!")'
Hello world!
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  9.22    0.000277           2       166        32 stat
  7.96    0.000239           3        94           fstat
  7.19    0.000216           3        79           read
  7.19    0.000216           3        68           rt_sigaction
  8.09    0.000243           4        58           close
 10.25    0.000308           5        57         2 openat
  1.63    0.000049           1        43         6 lseek
 17.78    0.000534          16        34           mmap
  0.43    0.000013           1        18           getdents
 12.62    0.000379          24        16           mprotect
  2.43    0.000073           6        12           brk
  1.66    0.000050           4        12         2 ioctl
  5.03    0.000151          17         9         9 access
  0.37    0.000011           1         8           lstat
  2.46    0.000074          19         4           munmap
  0.30    0.000009           3         3           dup
  0.27    0.000008           3         3         1 readlink
  0.23    0.000007           2         3           sigaltstack
  0.63    0.000019          19         1           write
  0.53    0.000016          16         1           rt_sigprocmask
  0.00    0.000000           0         1           getpid
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           fcntl
  0.00    0.000000           0         1           sysinfo
  0.00    0.000000           0         1           getuid
  0.00    0.000000           0         1           getgid
  0.00    0.000000           0         1           geteuid
  0.00    0.000000           0         1           getegid
  0.43    0.000013          13         1           arch_prctl
  0.80    0.000024          24         1           futex
  0.60    0.000018          18         1           set_tid_address
  0.63    0.000019          19         1           set_robust_list
  0.53    0.000016          16         1           prlimit64
  0.73    0.000022          22         1           getrandom
------ ----------- ----------- --------- --------- ----------------
100.00    0.003004                   703        52 total

Do output quá dài nên ở đây thay đổi câu lệnh, để có đầy đủ output hãy chạy với option C hoa:

$ strace -CScalls python -c 'print("hello world")'

Chương trình Python đơn giản này thực hiện tới 703 syscall, 52 fail.

Kết luận

27 với 703 thì cái nào “hơn”?

27 nhỏ hơn 703, còn 703 thì lớn hơn 27. Lập trình C cũng rất đơn giản, đúng không!

Vậy nên khi lập trình, luôn nhớ rằng mọi thứ đều là tương đôi, đều phải đánh đổi. Mấy em gái đã xinh mà code Python lại giỏi, chỉ có 2 khả năng xảy ra:

  • 1 là thiếu cái gì đó
  • 2 là học Python ở PYMI rõ ràng <3.

Đọc thêm

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

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

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

Các ưu nhược điểm của Swift so với Objective C

Các ưu nhược điểm của Swift so với Objective C

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Các ưu nhược điểm của Swift so với Objective C

Các ưu nhược điểm của Swift so với Objective C

1. Swift và Objective C

Swift và Objective-C là hai ngôn ngữ trong lập trình iOS.

Objective-C ra đời trước Swift và đã có lịch sử phát triển với rất nhiều ứng dụng.

Về sau Swift được phát triển để thay thế Objective-C. Swift cũng đi kèm với công cụ lập trình trực quan. Do đó, làm tới đâu thấy tới đó luôn, sẽ giúp ích nhiều cho các lập trình viên, đỡ tốn công debug.

Tuy nhiên Swift vẫn chưa thể thay thế ngay được Objective C.

Nếu bạn đã lập trình với cả C và Python thì bạn sẽ thấy Objective C giống C còn Swift giống Python. Swift lược bỏ đi khá nhiều những cú pháp phức tạp và rắc rối.

  Các cách sử dụng AS, AS?, AS! một cách hiệu quả và an toàn trong code Swift
  Arguments object trong javascript là gì? Cách sử dụng?

2. Các ưu điểm của Swift so với Objective C

  • Swift chạy nhanh hơn, tương đương với C++
  • Swift dễ đọc và dễ học hơn so với Objective-C (cú pháp hoàn toàn mới, ngắn gọn hơn rất nhiều)
  • Các file trong Swift thống nhất neenvieecj bảo trì code đơn giản hơn.
  • Compiler của Swift tốt hơn Objective C
  • Swift không sử dụng con trỏ giúp cho code an toàn hơn, và giúp lập trình viên lược bỏ phần khái niệm khó nhằn về con trỏ.
  • Swift quản lý bộ nhớ tốt hơn
  • Swift là mã nguồn mở: Lập trình viên có thể xem được mã nguồn, chỉnh sửa, vá lỗi.

3. Nhược điểm của Swift so với Objective C

  • Nhiều API không làm việc với Swift
  • Nhiều qui tắc khi khởi tạo, lựa chọn kiểu optional
  • Một lượng lớn các project, phần mềm trước đó đều viết bằng Objective C do đó Objective C.

Tóm tại, tuy tồn tại một số nhược điểm nhưng Swift vượt trội hoàn toàn so với Objective C. Trường hợp các dự án cũ, nhỏ thì bạn hoàn toàn có thể kết hợp cả 2 ngôn ngữ này.

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

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

Xem thêm Việc làm swift, tuyển dụng it hấp dẫn trên TopDev

Security Considerations khi Designing Web Applications

Security Considerations khi Designing Web Applications

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Nhắc tới thiết kế hệ thống (System Design), ngoài thiết kế hệ thống tốt, đáp ứng khả năng Scale, chuẩn business, ta cũng cần cân nhắc thêm về tính bảo mật của hệ thống (Security Considerations)

Qua bài viết dưới đây, Kieblog mong muốn chia sẻ thêm chút ít kinh nghiệm thực tế khi thiết kế hệ thống Web. Một số vấn đề về Security cần quan tâm.

Bắt đầu ngay thôi nào!

1. Access and Authentication

Access và Authentication là 2 phần không thể bỏ qua khi nói về Security Considerations cho Designing Web Applications. Hầu hết các cuộc tấn công Web hiện nay, nguyên nhân chủ yếu không phải là các cuộc tấn công lớn hoặc sử dụng công nghệ cao. Nguyên nhân chính là do hệ thống bảo mật yếu kém. Trong đó nổi bật nhất là Authentication.

Các vụ tấn công lớn đã được biết tới của Target Corp hay Yahoo đều xuất phát từ email. Đối tượng tấn công vào một node trong chuỗi cung ứng. Dẫn tới mật khẩu quản trị bị đánh cắp dẫn tới mất thông tin.

18 Web Developer Jobs

Tùy vào từng đối tượng website và yêu cầu về bảo mật, người thiết kế hệ thống có thể cân nhắc thêm:

Việc bổ sung bước thứ hai giúp giảm thiếu rủi ro bị đánh cắp dữ liệu, giao các quyền truy cập thông tin không được phép vào tay hacker.

Security Considerations

Trước tới nay, nhắc tới API, ta có thể nghĩ tới tới ngay SOAP Web Services. Tuy nhiên với GraphQL, có nhiều cách để take care hoặc đảm bảo API Access Secutiry.

Security Considerations

2. SSL – Http và Https

Về SSL, HTTPS và HTTP hẳn anh em cũng đã có hiểu biết nhiều. Hiện tại, Https đã là yếu tố bắt buộc của hầu hết các Website.

Nhắc lại một chút về định nghĩa.

SSL stands for Secure Sockets Layer and, in short, it’s the standard technology for keeping an internet connection secure and safeguarding any sensitive data that is being sent between two systems, preventing criminals from reading and modifying any information transferred, including potential personal details.

SSL là Secure Socket Layer, nó là công nghệ tiêu chuẩn để giữ an toàn cho các kết nối, bảo về dữ liệu an toàn khi được gửi đia giữa hai hệ thống, ngăn tội phạm đọc trộm hoặc chỉnh sửa bất kì thông tin nào khi đã được gửi đi, bao gồm thông tin chi tiết.

HTTPS (SSL or Secure Sockets Layer). Anh em nào chưa biết có thể tham khảo thêm ở đây

3. SQL Injection

Khi nói về Secutiry cho hệ thống Web (Security Considerations), không thể không nhắc tới SQL Injection. Đây là cách tấn công phổ biến và để lại hậu quả tại hại. Về cơ bản:

SQL injection is a code injection technique that might destroy your database. Is one of the most common web hacking techniques. Is the placement of malicious code in SQL statements, via web page input.

SQL Injection là kiểu tấn công phá hủy hệ cơ sở dữ liệu bằng cách thực hiện command ngay trên chính DB hệ thống, là kiểu tấn công cơ bản và được sử dụng nhiều. Thông qua input và Web, thực hiện các câu lệnh SQL nhằm ăn cắp hoặc phá hủy thông tin.

Về phương án xử lý hoặc phòng ngừa với SQL Injection cũng khá đơn giản. Hầu hết các ORM Framework hiện nay (Hibernate, JPA, MyBatis) đều đã hỗ trợ để ngăn chặn cuộc tấn công bằng SQL Injection

  • Java EE – use PreparedStatement() with bind variables
  • .NET – use parameterized queries like SqlCommand() or OleDbCommand() with bind variables
  • PHP – use PDO with strongly typed parameterized queries (using bindParam())
  • Hibernate – use createQuery() with bind variables (called named parameters in Hibernate)
  • SQLite – use sqlite3_prepare() to create a statement object
Security ConsiderationsNguồn ảnh / Source: portswigger.net

4. Command Injection

Gần giống như SQL Injection, Command Inject cũng tìm cách thực hiện hoặc run được command ở phía services của web.

Command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application

Mục tiêu của tấn công Comman injection là thực hiện tùy ý các lệnh trên hệ điều hành thông qua một ứng dụng dễ bị tấn công.

Trên góc nhìn cá nhân, cả SQL Injection và Command Injection đều nguy hiểm. Tuy nhiên Command Injection mang tới hậu quả khủng khiếp hơn, nếu một Server hoặc Services bị down, dù chỉ 5,10 phút cũng có thể gây ảnh hưởng rất lớn tới cá nhân, doanh nghiệp.

Về giải pháp thì có thể cân nhắc trong quá trình phát triển web:

  • Do not allow any user input to commands your application is executing – Không cho phép bất cứ input nào từ user command trên applicaton được thực thi.
  • Only use secure APIs for executing commands, such as execFile() – Chỉ sử dụng API đã secure để thực thi commands, như execFile().
  • When using execFile(), make sure the user has no control over the program name – Khi sử dụng execFile(), đảm bảo rằng user không kiểm soát tên chương trình.
Security ConsiderationsTop 10 command injection attacks. Nguồn ảnh/Source: snyk.io

Anh em có thể tham khảo thêm bài viết này về Command injection: how it works, what are the risks, and how to prevent it

5. Security Considerations Input Checks

Input check cũng là một yếu tố cần quan tâm khi nhắc tới Security Considerations. Input checks cũng gần giống với Access. Tuy nhiên input ở phía người dùng có vô vàn biến thể khác nhau (theo cách khó ngờ nhất).

Make sure to validate input fields on both the server and client side

Phải chắc chắn rằng ta luôn validate input field ở cả 2 phía server và client

Input field cũng có thể sử dụng blacklisting, chỉ cho phép những field whitelist validate, còn lại ignore tất cả.

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

6. Tham khảo

Đừng bỏ lỡ it jobs Developer mới nhất tại TopDev

Làm thế nào để làm theo “Hướng dẫn” một cách thông minh nhất?

làm việc với hướng dẫn
Làm thế nào để làm theo “Hướng dẫn” một cách thông minh nhất?

Tác giả: Jessica Wilkins

Hướng dẫn thực hiện các dự án là một cách rất phổ biến để bắt đầu xây dựng một vài kế hoạch đầu tiên của bạn. Nhưng đáng tiếc là hầu hết mọi người đều đi sai cách và không học được nhiều từ quá trình này. Trong bài viết này, tôi sẽ cung cấp một số mẹo về cách làm việc với hướng dẫn một cách hiệu quả nhất và có được sự tự tin để bắt đầu xây dựng các dự án của riêng bạn.

làm việc với hướng dẫn
Làm việc hiệu quả với hướng dẫn hơn

Tôi đã từng mắc kẹt trong chính những hướng dẫn như thế nào?

Khi tôi mới bắt đầu học cách viết code cách đây 9 tháng, tôi không hiểu rõ một quy trình làm thế nào để bắt đầu xây dựng dự án đầu tiên của mình. Vì vậy, tôi đã đăng ký một khóa học của Udemy và học cách xây dựng một trang web nhà hàng bằng HTML và CSS.

Tôi thích kết quả cuối cùng và quyết định đăng ký thêm một khóa học khác. Tôi đã học cách xây dựng trang đích sản phẩm với một số hình ảnh thú vị. Tôi đã rất tự hào về hai dự án này vì nghĩ mình đã làm được điều gì đó.

Nhưng khi tôi mở trình làm việc của mình, tôi đang vẽ một khoảng trống hoàn toàn. Tôi không có manh mối làm thế nào để bắt đầu hoặc làm thế nào để nghiên cứu. Sau đó, tôi nhận ra rằng trong suốt tháng qua, tôi đã bị mắc kẹt trong việc sử dụng các hướng dẫn mà không có kế hoạch chơi game. Tôi đã có cơ hội học hỏi từ những video này, nhưng tôi đã đi sai cách.

  Codepen là gì ? Hướng dẫn sử dụng Codepen cơ bản
  Hướng dẫn cài đặt Flutter SDK trên Linux

Tất cả những gì tôi đang làm là viết code cùng với người hướng dẫn và nhảy từ dự án này sang dự án khác. Tôi không dừng lại để đặt câu hỏi và xử lý những gì tôi vừa học được. Hướng dẫn có thể là một công cụ học tập tốt, nhưng bạn phải thực hiện nó theo cách đúng đắn, nếu không, bạn có thể trở nên phụ thuộc vào chúng và không thể tự học cách viết code.

Nên làm thế nào để hướng dẫn phát huy được hiệu quả thật sự?

Dưới đây là năm bước tôi dùng để làm việc với các dự án:

1. Nghiên cứu thật kỹ về dự án

Rất nhiều người khi mới bắt đầu, bao gồm cả tôi, sẽ chỉ đi thẳng vào video mà không suy nghĩ trước về dự án. Một phần quan trọng của việc trở thành một nhà phát triển là suy nghĩ về vấn đề trước tiên và sau đó lo lắng về việc triển khai.

Giả sử bạn muốn xem hướng dẫn về cách tạo công cụ thay đổi màu nền ngẫu nhiên. Quá trình suy nghĩ cơ bản của bạn có thể trông giống như sau:

  • Tạo ra một bộ sưu tập các màu sắc khác nhau
  • Tạo một nút mà khi nhấp vào sẽ thay đổi màu nền
  • Tạo một số loại chức năng ngẫu nhiên cho các lựa chọn màu sắc

Ngay cả khi bạn không biết cách triển khai điều đó thành code như thế nào, thì ít nhất bạn cũng đang bắt đầu suy nghĩ về vấn đề.

Xem thêm Kinh nghiệm xương máu sau 9 tháng làm Kỹ sư phần mềm (Phần 1)

2. Hãy thử xây dựng một kế hoạch bằng chính suy nghĩ của mình trước

Rất nhiều người ngại việc tự mình xây dựng một thứ gì đó vì sợ không có kỹ năng hoặc kiến ​​thức. Nhưng hãy cố gắng thử với một số vấn đề trước.

Trước khi xem video, bạn có thể thử chuyển đổi những vấn đề bạn đang nghĩ thành code trước. Nếu bạn Google “bộ sưu tập màu sắc JavaScript”, thì một trong những kết quả sẽ đề cập đến một mảng. Hoặc nếu bạn Google, “JavaScript hàm ngẫu nhiên”, thì kết quả đầu tiên sẽ dành cho Math.random().

Đây chính là cách để bạn triển khai code của mình. Chẳng có vấn đề gì kể cả nếu code của bạn không hoàn toàn đúng. Mục đích của điều này là bạn sẽ nghiên cứu được nhiều hơn và hiểu cặn kẽ được vấn đề mình đang làm việc.

kinh nghiệm lập trình

3. Xem video và đặt ra những câu hỏi

Sau khi đã suy nghĩ về dự án và bắt đầu thử một số cách code của riêng mình. Đã đến lúc bạn bắt tay vào xem video hướng dẫn. Tôi sẽ không khuyên bạn ngồi xuống và xem toàn bộ video mà không dừng lại.

Bộ não của bạn sẽ không thể nào tiêu thụ rất nhiều thông tin cùng một lúc. Sẽ tốt hơn nếu bạn tạm dừng video định kỳ để xử lý những gì bạn vừa học được. Nó cũng sẽ cho bạn cơ hội để nghiên cứu các khái niệm khiến bạn nhầm lẫn trong video.

Đặt câu hỏi và nghiên cứu là một kỹ năng quan trọng để trở thành một nhà phát triển thành công.

4. “Bóc tách” một dự án đã hoàn thành cũng giúp bạn rút ra rất nhiều kinh nghiệm

Sau khi bạn xem xong video và dự án đã hoàn thành, tôi muốn bạn phá hủy nó và cho mọi thứ trở lại từ đầu. Tạo các lỗi nhỏ trong dự án sẽ dạy bạn đọc hiểu các thông báo lỗi. Thông báo lỗi không phải lúc nào cũng là một điều xấu. Bạn có thể học được nhiều điều từ những lỗi này.

Ví dụ, có thể bạn đang thắc mắc tại sao người hướng dẫn lại chọn sử dụng let thay vì const trong một tình huống cụ thể. Hãy thử thay đổi nó thành const và xem điều gì sẽ xảy ra.

Có một thông báo lỗi? Nếu vậy, hãy đọc qua thông báo lỗi đó và bạn sẽ tìm hiểu lý do tại sao người hướng dẫn chọn sử dụng let hơn const.

  5 sai lầm thường thấy khi viết react component

5. Xây dựng lại dự án theo cách của riêng bạn

Nếu bạn muốn tự kiểm tra các khái niệm đã học trong video, hãy xây dựng lại dự án theo cách của riêng bạn. Hãy bắt đầu bằng cách chọn các phương pháp khác nhau từ người hướng dẫn.

Ví dụ: nếu người hướng dẫn sử dụng câu lệnh if / else, có thể bạn muốn thay đổi nó để chuyển đổi thành một câu lệnh khác. Hoặc nếu người hướng dẫn sử dụng một vòng lặp for đơn giản, có thể một vòng lặp forEach cũng sẽ hoạt động.

Bạn cũng có thể thêm một tính năng bổ sung vào dự án. Có thể bạn muốn tạo một số hoạt ảnh tùy chỉnh hoặc thử nghiệm với việc thêm âm thanh. Hoặc có thể bạn muốn sử dụng ứng dụng một trang đó và biến nó thành một trang web nhiều trang.

Học cách xây dựng lại dự án theo cách của riêng bạn sẽ bắt đầu mang lại cho bạn sự tự tin để tự xây dựng dự án. Nó cũng sẽ dạy bạn cách nghiên cứu, đặt câu hỏi và debug cho code của bạn.

Hướng dẫn làm việc với các dự án có thể là một công cụ học tập tuyệt vời nếu bạn sử dụng chúng đúng cách. Vậy nên hãy cố gắng để có thể sử dụng chúng một cách hợp lí và phát triển tư duy làm việc của riêng bạn.

Bài viết được phỏng dịch theo bài viết gốc tại freecodecamp.org

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

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

RxSwift 2: Khái niệm cơ bản về lập trình bất đồng bộ

RxSwift 2: Khái niệm cơ bản về lập trình bất đồng bộ

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

Đồng bộ và bất đồng bộ khác nhau như nào? Ví dụ, khi các bạn tính 1+ 1 trên máy tính casio bỏ túi thì nó ra luôn là 2, vậy kết quả đó là tức thời thì nó là đồng bộ. Còn giả sử bạn nhập 1 + 1 trên 1 trang web, rồi bấm nút kết quả, trang đó sẽ gọi lên server xử lý được kết quả và trả về lại cho web là 2 để hiển thị cho bạn, thì như vậy bạn phải đợi trong 1 khoảng thời gian nào đó, giả sử bạn dùng mạng miền núi mất 2s mới trả về, thì đó gọi là bất đồng bộ. Nói nôm na, cái gì mà phải chờ đợi thì bất đồng bộ, còn cái gì tức thời thì đồng bộ.

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

  RxSwift 10: Làm việc với PublishSubjects
  RxSwift 5: Cài đặt RxSwift

Còn trong 1 chương trình IOS, chúng ta có thể có rất nhiều thứ bất đồng bộ, ví dụ 1 app như sau:

  • Sự kiện khi bấm vào 1 nút(button) trên màn hình, ví dụ nút đăng nhập(chúng ta thực sự không biết lúc nào thì user bấm)
  • Hiển thị bàn phím hay ẩn bàn phím trên 1 ô text filed
  • Tải 1 file ảnh lớn từ internet(không biết bao lâu thì xong, tùy thuộc vào mạng nhà bạn)
  • Lưu dữ liệu xuống đĩa
  • Chơi 1 bài hát
  • Và nhiều nữa…

Và các sự kiện trên đều có thể xảy ra cùng 1 lúc, ví dụ bạn vừa nghe nhạc vừa tải 1 ảnh về, vừa mở ô text filed để nhập gì đó. Vậy chúng ta sẽ xử lý từng sự kiện riêng biệt đó như thế nào?

RxSwift 2: Khái niệm cơ bản về lập trình bất đồng bộ
Ứng dụng IOS làm những việc bất đồng bộ đồng thời

Tất cả các việc trên đều không ngăn chặn quá trình thực thi của nhau. IOS cung cấp các APIs để thực thi các việc khác nhau trên các luồng khác nhau(thread) trên các lõi khác nhau của CPU. Tuy nhiên việc viết mã song song khá phức tạp, đặc biệt các việc khác nhau lại cần nguồn dữ liệu giống nhau. Thật khó để xác định đoạn mã nào cập nhật dữ liệu trước hoặc đoạn mã nào có được dữ liệu mới nhất. (Ví dụ bạn không thể xác định được bao lâu thì ảnh mới tải xong, ảnh nào là tải xong đầu tiên…)

Cocoa và các API UIKit bất đồng bộ

Apple cung cấp rất nhiều API trong IOS SDK của họ để giúp bạn viết các đoạn mã bất đồng bộ. Bạn có thể đã sử dụng những thứ này tuy nhiên lại không biết mình đã từng sử dụng, cụ thể những thứ phổ biến mà bạn hay dùng như sau:

  • NotificationCenter: Để thực thi những đoạn code tại 1 thời điểm không biết trước nào đó, ví dụ khi người dùng cầm điện thoại để nó nằm ngang hay dọc, bàn phím ẩn hay hiện trên ứng dụng.
  • The delegate pattern: để thực thi các đoạn code được ủy quyền từ nơi khác, ví dụ bạn muốn xử lý khi có thông báo mới (push notification) đến ứng dụng.
  • Grand Central Dispatch: để giúp bạn thực thi các phần công việc. Bạn có thể viết mã để các công việc thực thi trong 1 hàng đợi nối tiếp hay chạy vô số tác vụ đồng thời trên nhiều hàng đợi khác nhau với sự ưu tiên khác nhau.
  • Closures: để tách các đoạn mã mà bạn có thể chuyển giữa các lớp, để mỗi lớp có thể quyết định thực thi nó hay không, bao nhiêu lần và khi nào

Vì đa số các lớp của bạn đều thực hiện những công việc không đồng bộ, các thành phần giao diện người dùng(UI) cũng hoạt động không đồng bộ, cho nên không thể xác định được mã của bạn sẽ thực thi theo thứ tự nào.

Tóm lại, ứng dụng của bạn hoạt động tùy thuộc vào điều kiện dữ liệu bên ngoài, như dữ liệu đầu vào người dùng, điều kiện mạng internet hay các sự kiện hệ điều hành khác. Mỗi khi người dùng mở ứng dụng của bạn, thì nó sẽ hoạt động khác nhau tùy thuộc vào các yếu tố bên ngoài đó. Chúng ta không hề nói rằng việc viết chương trình không đồng bộ là không thể, vì công bằng mà nói các API của apple là mạnh mẽ so với các nền tảng khác cung cấp.

Vấn đề là mã không đồng bộ trở nên phức tạp do sự đa dạng các API của apple cung cấp trong framework(SDK) của họ như sau:

RxSwift 2: Khái niệm cơ bản về lập trình bất đồng bộ

Việc sử dụng delegate bạn cần áp dụng theo mẫu, hoặc có lúc bạn lại sử dụng closure thay thế, hoặc cũng có thể dùng notification center. Không có 1 quy tắc chung nào cho các API trên, do vậy việc đọc hiểu cũng như suy luận logic code trở nên khó khăn(thích cái gì thì dùng cái đó, không có nguyên tắc cho developer).

Để kết thúc phần này, chúng ta sẽ nghiên cứu 2 đoạn mã đồng bộ và bất đồng bộ sau:

Synchronous code(mã đồng bộ)

Để thực hiện thao tác cho 1 phần tử của 1 mảng thì bạn đã dùng rất nhiều lần. Đó là logic ứng dụng rất đơn giản và có 2 điều bất biến: 1 là các thành phần của mảng, và 2 là nó thực thi đồng bộ.

Hãy thử đoạn code sau trên playground(xcode):

var array = [1, 2, 3]
for number in array {
  print(number)
  array = [4, 5, 6]
}
print(array)

kết quả như sau:

1
2
3
[4, 5, 6]

Rõ ràng mặc dù có thay đổi giá trị của array trong vòng for, tuy nhiên kết quả array vẫn không thay đổi trong quá trình thực thi vòng for. Nó chỉ thực sự thay đổi khi thoát ra khỏi vòng for.

Asynchronous code(mã bất đồng bộ)

Hãy tải code ở link sau:

https://github.com/lexuanquynh/RxLearning.git

hoặc mở xcode và tạo 1 chương trình có dạng:

class ViewController: UIViewController {
    var array = [1, 2, 3]
    var currentIndex = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    @IBAction func onButtonTouched(_ sender: Any) {
        print(array[currentIndex])
        if currentIndex != array.count-1 {
            currentIndex += 1
        }
    }
}

Mỗi lần bấm vào nút button trên màn hình, thì index sẽ in ra và tăng lên 1 cho đến khi nó khác 3. Nếu bạn không thể hiểu đoạn code trên thì nên xem lại kiến thức căn bản về lập trình swift nhé.

Vấn đề là, giả sử có 1 đoạn code khác cũng sử dụng mảng array trên, và trong khi bạn còn chưa bấm nút để tăng index, thì array bị thay đổi giá trị hay index bị thay đổi giá trị, dẫn đến kết quả không còn là 1, 2, 3 nữa. Do vậy với đoạn code bất đồng bộ như vậy sẽ rất khó quản lý kết quả như mong muốn. May mắn thay, RxSwift lại giúp ta việc đó.

Vậy chúng ta hãy tiếp tục trong bài 3 để hiểu rõ hơn về nó nhé.

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

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

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

Mypy – là trai hay là gái?

Mypy - là trai hay là gái?

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

Vài ba năm gần đây, làng Vũ Trụ rộn lên trào lưu thêm “type” vào các ngôn ngữ lập trình dynamic typing.

Python đã già nhưng vẫn đú, cũng không bỏ lỡ cuộc đu trend này. Kết quả là ngày hôm nay, bạn đã có thể thêm type vào code Python – nếu muốn – như DropBoxInstagram… . Python chính thức thêm type hint/type annotation vào từ bản 3.5, chú ý rằng type này không ảnh hưởng/giúp đỡ gì bạn, nếu không sử dụng mypy hay các IDE.

  7 lý do bạn không nên sử dụng TypeScript
  Học kiến thức căn bản TypeScript chỉ trong 30 phút

Mypy là static type checker – tool giúp phân tích code (static analysis) dựa trên type annotation, dự án có sự tham gia của tác giả Python – Guido van Rossum, … và cả HVN

Thêm type để làm gì?

Các ngôn ngữ lập trình dynamic typing: Python, JavaScript, PHP, Ruby được ưa chuộng và luôn chiếm vị trí top các bảng xếp hạng ngôn ngữ lập trình trong những năm gần đây, hay Clojure, LISP, Erlang, Elixir… dù không lên đỉnh nhưng vẫn luôn hot. Dynamic typing giúp code trở nên ngắn gọn và linh hoạt. Vậy thêm type (kiểu) làm gì? không lẽ để dài hơn và bớt linh hoạt hơn?

Code dài dòng thêm thì rõ là không ai muốn, bởi nếu muốn đã quay về viết Java hết rồi, nhưng bớt linh hoạt hơn là một mục đích đáng xem xét.

Khi mọi thứ linh hoạt, nếu không tuân theo các quy tắc, không có kỷ luật cá nhân tốt, sẽ dẫn tới rối loạn. Hoặc khi hệ thống trở nên phức tạp hơn, nhiều tính năng phụ thuộc vào nhau, cũng dẫn tới việc không kiểm soát được.

Điều này sẽ dễ thấy hơn khi tham gia một dự án có nhiều lập trình viên. Một team 5 Python dev làm việc đã quen với nhau, code cùng chuẩn PEP8, cùng không thích OOP, … hay nói cách khác là một team thực thụ, sẽ code nhanh như tên lửa, vài giờ một tính năng, bay vèo vèo như YouTube dev .

Một nhóm người khác với 5 lập trình viên, học lập trình từ các nguồn khác nhau, trình độ khác nhau, thậm chí ngôn ngữ thành thạo cũng khác nhau, nếu làm cùng một dự án sẽ rất rối loạn. Có chỗ viết 3 class để gọi 1 function cho đúng chuẩn kế thừa, OOP của Java, có function viết theo kiểu recursive, có chỗ đặt tên biến một chữ cái, không viết function, một hàm main dài hàng trăm dòng, function mỗi nhánh trả về một kiểu khác, viết decorator chỉ để dùng 1 lần và thể hiện, sửa một function rồi các function khác hỏng theo… và hàng trăm thứ khác có thể sai hơn nữa. Một team như vậy phát triển sẽ rất chậm, nhiều bug, khó thêm tính năng, thậm chí gây mệt mỏi, stress khi phải làm việc với nhau. Giải pháp thì lại không thể là giải tán, cãi nhau, vậy làm gì?

Type là một phần giải pháp, type giúp đặt ràng buộc rõ ràng đầu vào đầu ra, đảm bảo một function luôn trả về cùng 1 kiểu dù ở nhánh nào. Function là kiến trúc cơ bản của 1 chương trình, một hệ thống. Khi function định nghĩa rõ ràng, các bên tương tác (gọi function) với nhau cũng sẽ rõ ràng. Nhân viên mới tuyển, sinh viên mới ra trường, vào sửa function trả về nhầm kiểu sẽ bị type bắt lại ngay.

  • Type là một thứ CÔNG CỤ giúp giảm sự linh hoạt của code, tăng thêm kỷ luật, đảm bảo code ít bị rối loạn hơn. Nếu code 1 mình, hay bạn chắc chăn mình và các đồng nghiệp đủ kỷ luật để không viết function trả về các kiểu khác nhau thì type cũng không cần thiết.
  • Type không nên là thứ can thiệp/cản trở nhiều vào mục đích của lập trình viên. Ta muốn có công cụ trợ giúp, chứ không muốn nó chống lại mình. Type dài dòng như của Java là một ví dụ điển hình khiến việc viết code cũng trở nên ngại.

Sử dụng mypy

Cài đặt

pip install mypy

Ví dụ 1 – đơn giản để bắt đầu

Ví dụ 1: đoạn code không có type:

File mypy_simple.py

def sum_of_three(a, b, c):
    result = a + b + c
    return result

def main():
    result = sum_of_three(6, 9, 6) * 2
    message = "The answer of life: " + result
    print(message)

main()

Chạy mypy:

$ mypy mypy_simple.py
Success: no issues found in 1 source file

Không có gì xảy ra, do không function/name nào có type annotation cả. Mặc định này giúp việc thêm type là tùy ý. Team có thể có người viết type, có người không ở các function khác nhau, đều OK. Nếu cực nghiêm khắc, có thể bật chế độ strict lên:

$ mypy --strict mypy_simple.py
mypy_simple.py:1: error: Function is missing a type annotation
mypy_simple.py:5: error: Function is missing a return type annotation
mypy_simple.py:5: note: Use "-> None" if function does not return a value
mypy_simple.py:6: error: Call to untyped function "sum_of_three" in typed context
mypy_simple.py:10: error: Call to untyped function "main" in typed context
Found 4 errors in 1 file (checked 1 source file)

Ở chế độ này, mọi thứ thiếu type annotation đều bị thông báo, đây chỉ là ví dụ cực đoan, phải tốn khá nhiều công sức và làm quen mới có thể bật chế độ này lên, vậy nên khó quá tạm thời bỏ qua.

Thêm type cho đoạn code trong ví dụ 1: với Python type annotation, ta thường chỉ thêm cho định nghĩa của các function, ít khi phải khai báo cho các variable. Ví dụ trên có 2 function, sau khi thêm type vào sum_of_three sẽ trông như sau:

def sum_of_three(a: int, b: int, c: int) -> int:
    result = a + b + c
    return result

def main() -> None:
    result = sum_of_three(6, 9, 6) * 2
    message = "The answer of life: {}".format(result)
    print(message)

3 argument đều có kiểu là : int-> int nói rằng function này trả về kiểu int. Chạy lại lệnh mypy

$ mypy mypy_simple.py
Success: no issues found in 1 source file

Vẫn trông như không có gì xảy ra, nhưng thật ra là có, do code của ta không có vấn đề gì nên mypy cũng không báo gì. Thử đổi trong function main, cộng kết quả của sum_of_three (kiểu int) với một str:

def main() -> None:
    result = sum_of_three(6, 9, 6) * 2
    message = "The answer of life: " + result
    print(message)

Nếu là lập trình viên JavaScript, bạn sẽ mong đợi một kết quả str bình thường, "The answer of life: 42", bởi JavaScript thuộc loại weak typing, còn Python là strong typing: int là int, str là str, không cộng trừ lẫn lộn.

Nếu là một PyMier chân chính, bạn sẽ nhận ra ngay đoạn code này gặp exception khi CHẠY THẬT, do cộng một str với một số int.

$ python mypy_simple.py
Traceback (most recent call last):
  File "mypy_simple.py", line 12, in <module>
    main()
  File "mypy_simple.py", line 8, in main
    message = "The answer of life: " + result
TypeError: must be str, not int
Command exited with non-zero status 1

Vậy ta chỉ biết, khi chạy thật, mà lúc ấy mới biết thì “toang” rồi. Có cách nào biết trước khi chạy không? Mypy sẽ giúp làm chuyện ấy:

$ mypy mypy_simple.py
mypy_simple.py:8: error: Unsupported operand types for + ("str" and "int")
Found 1 error in 1 file (checked 1 source file)

Chú ý: việc phân tích function main chỉ xảy ra khi nó có type annotation:

def main() -> None:

Function main không nhận argument, trả về kiểu None. Nếu bỏ -> None đi, mypy sẽ không kiểm tra function main.

Ví dụ 2 – các containers: list, tuple, dict, set

from typing import List, Tuple

def with_index(names: List[str]) -> List[Tuple[int, str]]:
    return [(idx, name) for idx, name in enumerate(names)]

def main() -> None:
    result = 21 * 2

    result = with_index(["Corona", "Tiger Nau", "TrucBach"])
    print(result)

main()

Chỉ có str, int, float, bool, None là các kiểu dùng ngay. Với list, tuple, set, dict, cần phải import type tương ứng từ standard lib typing, các type viết Hoa chữ cái đầu. Có thể khai báo qua loa def with_index(names: List) -> List: hoặc chi tiết như trong ví dụ 2.

$ mypy mypy_simple.py
mypy_simple.py:11: error: Incompatible types in assignment (expression has type "List[Tuple[int, str]]", variable has type "int")

Lỗi này thường gặp, do chuyện dùng chung tên result, mypy lần đầu gặp sẽ nghĩ result là kiểu int, qua dòng tiếp theo lại suy luận nó được gán giá trị kiểu List[Tuple[int, str]]. Việc dùng một biến để chỉ tới nhiều kiểu khác nhau không hiếm trong dynamic typing, nhưng là chuyện không thể trong các ngôn ngữ static typing. Cách giải quyết chuẩn nhất là đổi tên biến.

Ví dụ 3 – các object phức tạp, thư viện bên ngoài

Với các lập trình viên Python, type là một thứ lạ, nên không phải dẽ gì ngồi đọc ngay ra kiểu của resp sau đây là gì mà gõ vào:

from typing import Any
import requests

def process_response(resp: Any, msg: str = 'From: ') -> str:
    return msg + resp.json()['origin']

r = requests.get('https://httpbin.org/ip')
output = process_response(r)# + 10
print(output)

Any giúp điền vào chỗ trống khi không biết kiểu gì, đồng nghĩa với việc mất đi một chút bảo vệ của mypy do mypy sẽ cho phép gọi function process_response với argument đầu tiên thuộc bất kỳ kiểu nào.

msg: str = 'From: ' là argument msg, kiểu str, với giá trị default From:.

$ python mypy_simple.py
From: 111.212.107.29

Có một cách khác để nhờ mypy tìm giúp kiểu của resp, đó là khai báo sai kiểu, thay Any thành int, chạy mypy sẽ thấy:

$ mypy mypy_simple.py
mypy_simple.py:5: error: "int" has no attribute "json"
mypy_simple.py:8: error: Argument 1 to "process_response" has incompatible type "Response"; expected "int"
Found 2 errors in 1 file (checked 1 source file)

Vậy kiểu của resp cần khai báo là Response, đầy đủ là requests.models.Response có thể tìm ra bằng cách print(type(r))

Ví dụ 4 – function nhận vào nhiều kiểu

Cũng có lúc, ta muốn chủ ý nhận vào nhiều loại input khác kiểu, nhưng chỉ giới hạn trong 1 nhóm, ví dụ như int, str, float, chứ không phải dict hay list, nếu dùng Any thì dễ dãi quá:

def any_number(n: int) -> str:
    return "This is {}".format(n)

any_number(6)
any_number("9")

### mypy check
error: Argument 1 to "any_number" has incompatible type "str"; expected "int"

Giải pháp là dùng Union.

from typing import Union

def any_number(n: Union[int,float,str]) -> str:

Các kiểu type khác: https://mypy.readthedocs.io/en/stable/kinds_of_types.html đáng chú ý như Optional khi có thể trả về None, hay Callable là kiểu cho function.

Stub

import boto3
mypy mypy_simple.py
mypy_simple.py:1: error: No library stub file for module 'boto3'
mypy_simple.py:1: note: (Stub files are from https://github.com/python/typeshed)

Sau khi Python chính thức thêm type notation, không có nghĩa là các core developer sẽ đi sửa hàng loạt các file thư viện đã chạy ổn định vài chục năm để thêm type. Thay vào đó, họ tạo ra các stub file. stub file là file chứa type annotation của các function trong library. Nó tương tự header file trong C/C++.

Ví dụ itertools

Các stub file của Python standard lib được gom lại tại python/typeshed.

Các thư viện bên ngoài thường ít khi có sẵn stub file, Ví dụ như boto3 – thư viện cực kỳ phổ biến – và chính thức để làm việc với API của AWS, tới nay vẫn chưa có stub file chính thức từ AWS. Nên để đơn giản, thay vì phải chiến đấu với type, ta có thể bỏ qua:

$ mypy --ignore-missing-import .

hay tự tạo stub như htlcnn. Xem hướng dẫn tự tạo stub file tại mypy wiki

Những vấn đề type giúp giải quyết

  • Kiểm tra kiểu, đảm bảo function trả về thống nhất một kiểu, nhận được đúng kiểu đầu vào.
  • Giúp nhìn vào dòng def (thuật ngữ chính xác: function signature) là biết luôn cần gọi với argument nào, trả về kiểu gì.

Những vấn đề type KHÔNG giúp giải quyết

  • Thay cho unittest: unittest dùng để kiểm tra logic chứ không phải để kiểm tra kiểu. Do không có ràng buộc về kiểu, nên trong unittest thường kiểm tra cả kiều của đầu ra function, việc này hoàn toàn bị loại bỏ khi dùng mypy.
  • Làm việc nhóm không hiệu quả: type chỉ là một phần giải pháp giúp xóa bớt sự chênh lệch trình độ giữa các lập trình viên. Bạn nên tìm cách đào tạo, chia sẻ kinh nghiệm, luyện tập cùng các đồng nghiệp thì hơn.

Hành động của chúng ta

Thêm ngay dòng sau vào Makefile, hay hệ thống CI của bạn, ngay sau pep8, flake8 hay pylint:

mypy --ignore-missing-import .

Kết luận

Type là một công cụ tốt cho các Pythonista như pylint pep8, giúp phát triển các dự án lớn hơn, nhiều người tham gia một cách dễ dàng hơn, trong khi việc đầu tư thì không có gì to tát cả – chỉ việc share bài viết này.

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

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

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

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Bài viết được sự cho phép của tác giả Trần Hữu Cương

CygWin là gì?

Cygwin là một bộ công cụ mã nguồn mở (GNU) dành cho Windows.

Cygwin cung cấp môi trường * nix (Unix) vào Windows bằng cách mô phỏng nhiều chi tiết nhỏ mà các hệ điều hành dựa trên Unix cung cấp. Do đó ta có thể chạy một số lệnh Unix trên Windows thông qua Cygwin.

Cygwin không phải là một trình biên dịch C/C++ (khả năng biên dịch C/C++ chỉ là một phần của nó). Chính vì CygWin có khả năng biên dịch C/C++ nên khi lập trình C/C++ người ta hay cài CygWin và coi nó như một trình compiler C/C++.

  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  Hướng dẫn cấu hình compiler MinGW, Cygwin cho Dev C++

Cài đặt CygWin trên hệ điều hành Windows

Trong ví dụ này mình cài đặt CygWin trên Windows 10.

Download bản cài đặt cygwin tại:  https://cygwin.com/install.html. Tùy vào máy của mình mà bạn download bản 64bit hay 32bit nhé.

Máy mình là Windows 64bit nên mình sẽ tải bản CygWin 64bit

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Click đúp vào file .exe vừa tải về

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Chọn thư mục cài CygWin:

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Chọn thư mục sẽ chứa các file tải về trong quá trình cài đặt CygWin:

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Chọn một site bất kỳ:

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Phần packages, ngoài các package mặc định được cài, bạn có thể chọn thêm các packages khác:

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Ví dụ mình muốn cài thêm package unzip và zip (chạy lệnh unzip và zip trên command line)

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows  CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Kết quả sau khi cài đặt CygWin thành công:

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Tìm việc làm C++ nhanh chóng trên TopDev

Tạo biến môi trường cho CygWin

Tiếp theo, thêm thư mục vừa cài đặt CygWin vào biến môi trường của Windows (để bạn có thể chạy các lệnh của CygWin bất kỳ folder nào)

Mở My Computer , click chuột phải vào khoảng trống và chọn Properties

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Chọn Tab Advanced và click Enviroment Variables

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Click vào phần Path và chọn Edit

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Click New và thêm folder bin của thư mục cài MinGW sau đó click OK.

(Bên trên mình cài MinGW ở C:\cygwin64 nên thư mục bin sẽ là C:\cygwin64\bin)

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Kiểm tra version của bản Cygwin vừa cài bằng lệnh:

  • cygcheck vesion

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Ở bên trên mình có cài đặt thêm pakage unzip, nên mình có thể sử dụng lệnh unzip bên trong cửa sổ dòng lệnh:

CygWin là gì? Cài đặt Compiler C/C++ CygWin trên Windows

Okay, Done!

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

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

Một vài điều cần lưu ý khi bạn làm việc với JS

Một vài điều cần lưu ý khi bạn làm việc với JS

Bài viết được sự cho phép của tác giả Lưu Bình An

Array.sort() cho kết quả khác nhau trên các trình duyệt khác nhau

Khi bạn cần sort các phần tử trong một mảng, khả năng rất cao là bạn sẽ sử dụng callback như: sort((x, y) => x < y).

  10 câu hỏi javascript để nâng cao trình độ
  10 trình quản lý file hàng đầu trong JavaScript

Đây là kết quả của Chrome và Firefox

Một vài điều cần lưu ý khi bạn làm việc với JS

Hàm callback chúng ta truyền vào phải return một trong ba giá trị 1, 0, -1, vì chúng ta đang return một giá trị boolean, nên sẽ tùy vào trình duyệt quyết định

Sử dụng JSON.stringify với tham số

Là một web developer, ít nhất một lần trong đời bạn sẽ sử dụng đến hàm JSON.stringify. Nhưng bạn có biết hàm này còn một tham số thứ 2 có thể truyền vào? Nó sẽ được sử dụng như một danh sách whitelist khi parse (chỉ có những giá trị key nằm trong whitelist mới được parse)

Một vài điều cần lưu ý khi bạn làm việc với JS

Không chỉ giới hạn là một mảng, có thể truyền một function để validatereplaceparse cặp keyvalue nhận được

Một vài điều cần lưu ý khi bạn làm việc với JS

Array.filter() không làm việc với Promise

Một công việc cũng hay sử lý trên mảng: thực hiện một số xử lý async trên các phần tử trong mảng, lặp qua các phần tử để xử lý dữ liệu rồi filter những phần tử không mong muốn.

Ví dụ, để kiểm tra user có quyền thực hiện một số tính năng nào đó không, chúng ta cần kiểm tra tất cả các giá trị trong mảng permissions

Một vài điều cần lưu ý khi bạn làm việc với JS

Một vài điều cần lưu ý khi bạn làm việc với JS

Code trên hoàn toàn hợp lý và đúng 100%

Tính huống tiếp theo, nếu bên trong hàm userCan chúng ta có một xử lý async?

Một vài điều cần lưu ý khi bạn làm việc với JS

Không chạy đúng đâu. Để sửa lại cho nó chạy đúng, chúng ta phải dùng map trước khi dùng đến filter

Một vài điều cần lưu ý khi bạn làm việc với JS

Nullish vs OR

Ai cũng biết viết OR

const foo = buzz || 'fallback'

Trong trường hợp bạn muốn foo bằng 0 khi buzz bằng 0, nói cách khác 0 vẫn được xem là một giá trị hợp lệ thì cách viết trên toang.

Một vài điều cần lưu ý khi bạn làm việc với JS

Nullish tương đối mới và được hỗ trợ từ TypeScript 3.7, các phiên bản trình duyệt mới, cũng nên lưu ý điểm này nhé.

Promise constructor anti-pattern

Tạo một Promise không vì một lý do gì cả.

Nếu bạn có một xử lý async thì bản chất nó đã return một promise, việc bạn new Promise chẳng có ý nghĩa gì cả

Một vài điều cần lưu ý khi bạn làm việc với JS

Chỉ đơn giản return fetchThing() là được (fetchThing là một async function)

Một vài điều cần lưu ý khi bạn làm việc với JS

Catch await error

Nếu sử dụng Promise bạn sẽ dùng then và catch, còn dùng async/await bạn sẽ dùng try/catch như thế này

Một vài điều cần lưu ý khi bạn làm việc với JS

Một cách thần kỳ chúng ta vẫn có thể dùng .catch ngay trên await

Một vài điều cần lưu ý khi bạn làm việc với JS

Nếu ngồi chiêm nghiệm thật kỹ bạn sẽ hiểu vì sao chúng ta vẫn viết được như vậy, gợi ý await là một cách viết cũng dựa trên Promise mà ra

Optional chain trên function

Optional chain trong object không xa lạ, nhưng optional chain trên function thì bạn có dùng chưa?

Một vài điều cần lưu ý khi bạn làm việc với JS

Một tình huống bạn sẽ sử dụng rất nhiều trong React là callback prop. Sẽ không còn cần phải viết onClick={onClick && () => onClick(param)}

10 Things 2020 has taught me

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

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

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

Thiết kế Messaging Service WhatsApp – P2

Thiết kế Messaging Service WhatsApp

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Tiếp theo phần 1 về thiết kế hệ thống Messaging Service WhatsApp. Bài viết thứ hai này sẽ cho ta một cái nhìn toàn diện và sâu hơn về thiết kế tổng quan đã trình bày ở phần trước.

Nội dung này có thể xem là High Level Design cho System. Trình bày và giải thích cụ thể hơn cho từng thành phần trong hệ thống.

  Discord đã lưu trữ hàng tỉ messages mỗi ngày như thế nào
  Kiểm tra HTML5 validation message

1. Quay lại với hệ thống

Quay lại với hệ thống Messaging Service WhatsApp, ở phần 1 ta đã có cái nhìn tổng quan về các thành phần trong hệ thống.

  • Load Balancer
  • App Servers
  • Memcached
  • APN/GCM
  • Job Queue
  • Workers
messaging-service-design-system

Tiếp tục đi sâu hơn nhằm trả lời các câu hỏi có thể phát sinh trong thực tiễn khi triển khai hệ thống.

2. Chi tiết Messaging Service WhatsApp

Bắt đầu từ gốc tới ngọn, ta sẽ xem xét Database Model trước. Ở hệ thống chat này, ta có thể sử dụng NoSQL, có 2 phương án để lựa chọn:

2.1 Database Model

  • Thứ nhất là Wide-Column Store. Loại này tương tự như HBase và Cassandra
  • Thư hai là NoSQL Key Value Stores, kiểu lưu trữ này chỉ có key và value, phân tán trên nhiều database nhỏ (Distributed Database). Tốt cho scaling, tiêu biểu có thể chọn là DynamoDB

Schema User như sau:

Java
- id

- username

- password

- device_OS // Xác định service gửi notification

- device_token // Dùng cho Notification

- list<unread_messages>

Lưu ý là bảng User cần có thêm 2 cột là device_OS và device_token. Device_OS cho ta biết nên sử dụng Apple APNS hay Google’s GCM. Device_token để làm việc với các service.

2.2 Distributed Cache

Distributed Cache giúp cải thiện hiệu năng hệ thống, với hệ thống chat, số lượng tin nhắn chờ đọc (unread mesage) rất nhiều. Nếu chỉ giữ ở Distributed Database sẽ dẫn tới database truy xuất quá nhiều lần

Java

- user_id

- list<unread_messages>

List user_id là tương tự với list_user ở table user trong database NoSQL. Sau khi user đã đọc message, ta sẽ xóa nó khỏi Cache. Cache thông thường sẽ được lưu ở RAM, dẫn tới việc không thể lưu quá nhiều. Sau khi đã đọc thì sẽ xóa nó đi, hình thức tương tự như Queue First-In-First-Out (FIFO)

3. Phân tích tính năng – Feature Walkthrough

Sau khi đã cái nhìn toàn diện về các thành phần trong hệ thống, ta sẽ tìm hiểu tiếp về các Feature (tính năng). Hệ thống chat tất nhiên những tính năng quan trọng nhất sẽ là

  • Sending a Message – Gửi tin nhắn
  • Receiving a Message – Nhận tin nhắn

3.1 Gửi tin nhắn

Khi có request từ phía client gửi tin nhắn. Ta có thể hiện thực method sau

Java

sendMessage(string message_text, int sender_id, int reciever_id)

AppServer sẽ handle sender_id (người gửi) và receicer_id (người nhận). Ngoài ra, AppServer cũng đảm nhận nhiệm vụ cung cấp time_stamp (thời gian gửi). Thành phần có thể được sử dụng làm key trong table, do thời gian không bao giờ trùng lặp nhau.

Thuộc tính của message sẽ bao gồm: <message_text, sender_id, timestamp>. App Server lúc này sẽ thêm nội dung message vào 2 chỗ:

  • The Distributed Cache – in User reciever_id’s list of unread messages.
  • The NoSQL Store – Again, in User reciever_id’s list of unread messages.

Sau khi đã lưu trữ message, sẽ tiếp tục gửi request notification tới APNS/GCM (tùy thuộc vào device_OS). Phần tính năng gửi tin nhắn xem như xong, tiếp tục là Receiving a Message – Nhận tin nhắn

3.2 Nhận tin nhắn

Khi nhận được notification, click vào notification sẽ open app và gọi tới server để lấy unread message. Nội dung request chắc chắn sẽ cần tới receiver id (người nhận tin nhắn).

Java

getUnreadMessages(int reciever_id)

App Server sẽ thực hiện query từ cache với reciever_id, nếu nội dung tìm thấy, thực hiện trả response cho device. Nếu trong cache không tồn tại tin nhắn, App Server sẽ thực hiện query tới NoSQL Database (trả về nếu tồn tại).

Một lưu ý nhỏ về timestamp, timestamp sẽ lấy giờ ở Server, không thể sử dụng timestamp ở phía device do thiết lập giờ ở phía client có thể sai. Hoặc cũng có trường hợp timezone của device khác nhau giữa các quốc gia.

Sau khi đã nhận được tin nhắn, phía server sẽ thực hiện xóa unread message từ cache thông qua một job bất đồng bộ (asynchronous job).

App cũng sẽ không hiển thị status “sent” cho tới khi nó được gửi thành công tới Server

3.3 Websocket

Trường hợp sử dụng WebSocket, ta có thể thiết lập connect alive 24/7 từ phía client tới server. Tuy nhiên, không phải device nào cũng online liên tục, nên nếu giữ kết nối liên tục sẽ dẫn tới lãng phí tài nguyên

  • One way to do this is to keep a WebSocket connection alive 24/7 for each device. Nếu giữ kết connection 24/7, sẽ lãng phí tài nguyên.
  • Another way is to set up the WebSocket connection as soon as the messaging app becomes active, i.e, the user opens the app. Cách khác là chỉ mở connection khi messaging app được bật trở lại.

Nếu User A (Server X) muốn nhắn tin cưa cẩm User B (connect tới Server Y), ta sẽ cần TCP connect giữa 2 server.

System design lúc này cần bổ sung thêm kết nối giữa các server với nhau.

Trường hợp một Client lost connection tới Server (thực tế diễn ra thường xuyên). Distributed Cache in memory lúc này trở nên hữu dụng, unread message vẫn được giữ ở đây để gửi cho user khi user online trở lại.

Trời má, viết hoài không hết, vậy vẫn phải cần Part 3 để trả lời thêm cho một số câu hỏi:

  • Which server will send Push Notifications? – Server nào sẽ chịu trách nhiểm đẩy noti đi
  • Will servers send entire messages to each other? – Có cần phải gửi tất cả tin nhắn đi không?
  • How to handle Chat Server failures? – Xử lí chat server thế nào khi failures?

4. Tham khảo

Thank you again for read all part of article – Have a great job – Happy coding!

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

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

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

JavaScript Runtime Environment là gì?

JavaScript Runtime Environment là gì?

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

Một khái niệm, thành phần khá quan trọng trong lập trình JavaScript đó là JavaScript Runtime Enviroment.

JavaScript Runtime Environment là gì?

Trước tiên, mình giải thích lại cách hoạt động của JavaScript. JavaScript khác với các ngôn ngữ biên dịch như C/C++. JavaScript chạy trong một container – container này chính là một phần mềm thực hiện đọc code JavaScript và thực thi nó.

Phần đọc code và chuyển thành các đoạn mã để container có thể hiểu chính là nhiệm vụ của JavaScript Engine.

Phần thực thi các đoạn mã đó lại thuộc về JavaScript Runtime Enviroment. JavaScript Runtime Enviroment cung cấp các đối tượng, môi trường để JavaScript giao tiếp với máy tính.

  Các thuật toán sắp xếp phổ biến trong JavaScript

Ví dụ Chrome Browser và Node.js đều sử dụng chung JavaScript Engine là V8. Tuy nhiên JavaScript Runtime Enviroment trong 2 trường hợp này lại khác nhau:

  • Chrome Browser sử dụng các đối tượng như window, DOM object hay các method như AJAX… để giao tiếp với network và hiển thị.
  • Node.js lại cung cấp các thư viện cho phép truy cập trực tiếp các file trên máy tính, truy cập database, tiến trình (Chrome Browser không làm được các việc này)

Ví dụ: dưới đây chính là JavaScript Runtime Enviroment hoạt động trên Chrome Browser:

JavaScript Runtime Environment là gì?

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

  JavaScript Runtime Environment là gì?
thêm một lần nào nữa”]

Xem thêm Javascript Jobs hấp dẫn trên TopDev