Home Blog Page 113

Cài đặt Spring Boot CLI

Cài đặt Spring Boot CLI

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

Bài viết sẽ hướng dẫn bạn cách cài đặt Spring Boot CLI phiên bản mới nhất (1.4.0.RELEASE tại thời điểm viết bài) trên Mac OS X (El Captain 10.11.6). Bạn download file này: http://repo.spring.io/release/org/springframework/boot/spring-boot-cli/1.4.0.RELEASE/spring-boot-cli-1.4.0.RELEASE-bin.tar.gz

  Giao tiếp Client / Server bằng gRPC
  Button Bootstrap: Cách tạo các loại button trong Bootstrap

THIẾT LẬP BIẾN MÔI TRƯỜNG

Sau đó giải nén, các tập tin cài đặt sẽ nằm trong thư mục spring-1.4.0.RELEASE . Mở file INSTALL.txt để xem hướng dẫn.

Giả sử, sau khi giải nén, thư mục chứa các tập tin cài đặt là:

/Users/donhuvy/Downloads/spring-1.4.0.RELEASE

thì bạn sẽ thiết lập biến môi trường như sau, gọi text editor Vim, sửa tập tin .bash_profile  bằng lệnh:

Gõ phím i để bắt đầu chế độ insert trong Vim, chèn thêm nội dung sau vào cuối tập tin:

Để lưu tập tin và thoát khỏi Vim, bạn gõ esc:wq!

Để kiểm tra chắc chắn nội dung mới đã ghi vào đúng cách, gõ lệnh:

Di chuyển đến cuối trang nội dung để thấy các nội dung thêm vào đã có. Để thoát khỏi lệnh tail, gõ control + C .

Để biến môi trường kể trên có hiệu lực, có 2 cách:

Cách 1: Gõ lệnh:

Cách 2: Đóng tất cả các cửa sổ Terminal, thoát Terminal, sau đó mở lại.

CÀI ĐẶT HỖ TRỢ AUTO-COMPLETE (khi gõ lệnh trong Spring Boot CLI)

Di chuyển đến thư mục chứa tập tin cài đặt (ở bước này, trên mỗi máy khác nhau có thể sẽ khác nhau):

Kiểm tra chính xác thư mục hiện tại:

Kiểm tra các tập tin trong gói cài đặt:

Tạo thư mục  /etc/bash_completion.d  bằng quyền của super admin:

Tạo thư mục  /usr/local/share/zsh/sitefunctions bằng quyền của super admin:

Tạo liên kết biểu tượng (symbolic link, trong Windows gọi là short-cut):

tương tự:

Hoàn thành xong bước này, Spring CLI đã hỗ trợ auto-complete.

Cài đặt Spring Boot CLI

KIỂM TRA KẾT QUẢ

Nếu thấy kết quả trả về là:

có nghĩa là quá trình cài đặt Spring Boot CLI đã thành công.

ỨNG DỤNG SPRING BOOT ĐẦU TIÊN

Kiểm tra thư mục hiện hành:

Tạo tập tin SmarjobWebController.java trong thư mục hiện hành:

Biên soạn nội dung tập tin:

Chạy ứng dụng:

Cài đặt Spring Boot CLI

Chúc mừng bạn, bạn vừa hoàn thành một ứng dụng Java web sử dụng Spring Framework, với sự hỗ trợ của Spring Boot (Source base này rất ổn định, là enterprise-class). Đây là cách làm rất nhanh, đặc sắc, chứng tỏ bạn am hiểu về Spring Boot khi khởi tạo cả một ứng dụng đồ sộ chỉ từ giao diện dòng lệnh (CLI: Command Line Interface).

Mẹo: Để thay đổi URL cho controller, hãy sửa giá trị mapping trong annotation @RequestMapping(“/your/prefer/url/path/foo/”)

Series bài viết chuyên sâu về Spring Framework đã được gắn tag: https://smartjob.vn/topic/spring-framework/

Bài viết gốc được đăng tải tại smartjob.vnĐỗ Như Vý

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

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

Một vài pattern để viết component của React cần dùng chung state

Một vài pattern để viết component của React cần dùng chung state

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

compound component

Khi gặp tình huống một component không thể đứng độc lập, mà nó buộc phải kết hợp với một component khác và cùng chia sẻ một bộ state và phương thức. Đó là lúc chúng ta cân nhắc cách viết compound component.

Một ví dụ rất dễ thấy của compound component là element <select /> và <option /><option/> không thể đứng độc lập, nó luôn được đặt trong <select/> có thể truy xuất và gọi các phương thức tương tự như <select/>

Tìm việc làm lập trình viên React

Tại sao lại sử dụng compound component?

Nếu bạn là người viết component, người khác sử dụng component này, các dev khác sẽ cảm ơn bạn rất nhiều. Bạn đóng gói mọi thứ logic vào bên trong component cha như vậy, người sau sẽ không cần bận tâm nữa.

// parent component
// xử lý event onChange, quản lý state selected value
<RadioImageForm>
	<RadioImageForm.RadioInput />
	<RadioImageForm.RadioInput />
	<RadioImageForm.RadioInput />
</RadioImageForm>

Với child component của <RadioImageForm />, để cho nó rõ ràng minh bạch là chúng ta sẽ sử dụng những giá trị cung cấp từ parent, chúng ta dùng kiểu viết <RadioImageForm.RadioInput />

export class RadioImageForm extends React.Component<Props, State> {
	static RadioInput = ({
		currentValue,
	    onChange,
	    label,
	    value,
	    name,
	    imgSrc,
	    key,
	}: RadioInputProps): React.ReactElement => (
		// ...
	);
	onChange = (): void => {
	  // ...
	};

  state = {
    currentValue: '',
    onChange: this.onChange,
    defaultValue: this.props.defaultValue || '',
  };

  render(): React.ReactElement {
    return (
      <RadioImageFormWrapper>
        <form>
        {/* .... */}
        </form>
      </RadioImageFormWrapper>
    )
  }
}

Một nhu cầu rất phổ biến là người khác sẽ muốn control component con <RadioInput /> bằng việc truyền thêm prop, nhưng thay vì truyền thằng vào component con, chúng ta hãy để họ truyền thông qua component cha <RadioImageForm/>, vì một lý do nào đó chúng ta cần truy cập các prop này bên trong component cha thì sao? Chúng ta làm thêm một bước pass-through các prop xuống cho component con với React.Children.map hoặc React.cloneElement

render(): React.ReactElement {
  const { currentValue, onChange, defaultValue } = this.state;

  return (
    <RadioImageFormWrapper>
      <form>
        {
          React.Children.map(this.props.children, 
            (child: React.ReactElement) =>
              React.cloneElement(child, {
                currentValue,
                onChange,
                defaultValue,
              }),
          )
        }
      </form>
    </RadioImageFormWrapper>
  )
}

Quay lại với <RadioInput />

static RadioInput = ({
  currentValue,
  onChange,
  label,
  value,
  name,
  imgSrc,
  key,
}: RadioInputProps) => (
  <label className="radio-button-group" key={key}>
    <input
      type="radio"
      name={name}
      value={value}
      aria-label={label}
      onChange={onChange}
      checked={currentValue === value}
      aria-checked={currentValue === value}
    />
    <img alt="" src={imgSrc} />
    <div className="overlay">
      {/* .... */}
    </div>
  </label>
);

Toàn bộ source code: https://codesandbox.io/s/compound-components-radio-image-form-k1h8x

  3 bước tối ưu hiệu năng React App bằng các API mới của React
  5 dự án React buộc phải có trong porfolio của bạn

Hạn chế

Với cách viết compound component này, chúng ta bị một hạn chế là bắt buộc phai viết component theo kiểu

<RadioImageForm>
	<RadioImageForm.RadioInput />
	<RadioImageForm.RadioInput />
	<RadioImageForm.RadioInput />
</RadioImageForm>

Chúng ta không được phép chèn thêm một số thẻ <div /> ở giữa nếu có nhu cầu tùy biến giao diện chẳng hạn

<RadioImageForm>
	<div>
	<RadioImageForm.RadioInput />
	<RadioImageForm.RadioInput />
	<RadioImageForm.RadioInput />
	</div>
</RadioImageForm>

Compound component Compound component với React Hook

Flexible compound component

Flexible compound component ra đời để giải quyết hạn chế của compound component, chúng ta sẽ sử dụng React Context API.

Chúng ta sẽ tạo ra một context mà ở đó cả component con và cha điều có thể truy xuất được, đúng như mục đích ra đời của Context API

const RadioImageFormContext = React.createContext({
  currentValue: '',
  defaultValue: undefined,
  onChange: () => { },
});
RadioImageFormContext.displayName = 'RadioImageForm';

Chúng ta sẽ refactor lại <RadioImageForm/>, bỏ đi đoạn React.Children.map, thay bằng <Provider />

render(): React.ReactElement {
  const { children } = this.props;

  return (
    <RadioImageFormWrapper>
      <RadioImageFormContext.Provider value={this.state}>
        {children}
      </RadioImageFormContext.Provider>
    </RadioImageFormWrapper>
  );
}

Sử dụng Provider có một lưu ý sống còn là đừng bao giờ truyền value={{ some bla bla}}, như vậy nó sẽ khác nhau trên tất cả những lần render, hãy nhớ truyền một thứ gì đó cache được và chỉ bị thay đổi khi cần thiết như this.state

Trong component con <RadioInput /> chúng ta có thể truy xuất tất cả dữ liệu nội bộ thông qua consumer, bởi vì <RadioInput /> đang nằm trong <RadioImageForm /> luôn theo cách viết của chúng ta, nên có thể khai báo một static property Consumer bên trong RadioImageForm

export class RadioImageForm extends React.Component<Props, State> {
  static Consumer = RadioImageFormContext.Consumer;
  //...

Source code ví dụ Source code Flexible compound component bằng functional component

Provider Pattern

Provider pattern là kỹ thuật kết hợp giữa React Context API và render props pattern, vẫn là để giải quyết câu chuyện chia sẻ state giữa các component trong cây.

Nếu bạn có thắc mắc, ủa vậy sao không dùng Redux, Mobx, Recoil, React Sweet State, Rematch, Unstated,… cho khỏe người ơi? Thì câu trả lời của mình là, ừ các bạn nên xài những thư viện quản lý state như vậy cho khỏe người, khỏe cho cả người maintain code bạn. Còn đây là cách làm nếu bạn muốn tham khảo, nếu không dùng gì hết, tôi dư giả thời gian để code từ đầu thì bạn có thể go-ahead với cách này

// src/components/DogDataProvider.tsx
interface State {
  data: IDog;
  status: Status;
  error: Error;
}

const initState: State = { status: Status.loading, data: null, error: null };

const DogDataProviderContext = React.createContext(undefined);
DogDataProviderContext.displayName = 'DogDataProvider';

const DogDataProvider: React.FC = ({ children }): React.ReactElement => {
  const [state, setState] = React.useState<State>(initState);

  React.useEffect(() => {
    setState(initState);

    (async (): Promise<void> => {
      try {
        // MOCK API CALL
        const asyncMockApiFn = async (): Promise<IDog> =>
          await new Promise(resolve => setTimeout(() => resolve(DATA), 1000));
        const data = await asyncMockApiFn();

        setState({
          data,
          status: Status.loaded,
          error: null
        });
      } catch (error) {
        setState({
          error,
          status: Status.error,
          data: null
        });
      }
    })();
  }, []);

  return (
    <DogDataProviderContext.Provider value={state}>
      {children}
    </DogDataProviderContext.Provider>
  );
};
// src/components/DogDataProvider.tsx

export function useDogProviderState() {
  const context = React.useContext(DogDataProviderContext);

  if (context === undefined) {
    throw new Error('useDogProviderState phải được sử dụng bên trong DogDataProvider.');
  }

  return context;
}
// src/index.tsx
function App() {
  return (
    <Router>
      <div className="App">
        {/* DataProvider phải nằm trên cùng của cây.*/}
        <DogDataProvider>
          <Nav />
          <main className="py-5 md:py-20 max-w-screen-xl mx-auto text-center text-white w-full">
            <Banner
              title={'React Component Patterns:'}
              subtitle={'Provider Pattern'}
            />
            <Switch>
              <Route exact path="/">
                {/* Component con sử dụng dữ liệu qua Consumer */}
                <Profile />
              </Route>
              <Route path="/friends">
                {/* Component con sử dụng dữ liệu qua Consumer */}
                <DogFriends />
              </Route>
            </Switch>
          </main>
        </DogDataProvider>
      </div>
    </Router>
  );
}
const Profile = () => {
  // custom hook nhận "subscribes" khi có state thay đổi
  const { data, status, error } = useDogProviderState();

  return (
    <div>
      <h1 className="//...">Profile</h1>
      <div className="mt-10">       
        {error ? (
          <Error errorMessage={error.message} />
        ) : status === Status.loading ? (
          <Loader isInherit={true} />
        ) : (
          <ProfileCard data={data} />
        )}
      </div>
    </div>
  );
};

Source Code Provider Pattern

React Component Patterns

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

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

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

Sử dụng publisher confirm trong RabbitMQ

Sử dụng publisher confirm trong RabbitMQ

Bài viết được sự cho phép của tác giả Giang Phan

Publisher confirms là một extension của RabbitMQ để thực hiện publish Message đáng tin cậy. Khi publisher confirms được bật trên một Channel, các Message mà Producer  publish phải được xác nhận bởi Broker là đã nhận thành công/ thất bại. Từ đó chúng ta có thể ghi log, thông báo lỗi và / hoặc retry gửi tin nhắn. Trong bài viết này tôi sẽ hướng dẫn bạn sử dụng tính năng này.

  Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud
  Sử dụng publisher confirm trong RabbitMQ
Phần 12 : Kết nối RabbitMQ”]

Enabling Publisher Confirms trên một Channel

Publishers confirms không được enable theo mặc định. Để enable chúng ta gọi phương thức confirmSelect().

Channel channel = connection.createChannel(); channel.confirmSelect();

Phương thức này phải được gọi trên mọi Channel mà ta muốn sử dụng, chỉ nên được kích hoạt một lần cho một Channel, không phải cho mọi Message được publish.

Để biết một Message đã được publisher confirm hay chưa, chúng ta đăng ký một callback để được notify về kết quả publish:

Channel channel = connection.createChannel();
channel.confirmSelect();
channel.addConfirmListener((sequenceNumber, multiple) -> {
    // code when message is confirmed
}, (sequenceNumber, multiple) -> {
    // code when message is nack-ed
});

Có 2 callback:

  • Một cho Message được xác nhậ.
  • Một cho tin nhắn nack-ed (tin nhắn có thể được coi là bị mất bởi boker).

Mỗi callback có 2 tham số:

  • sequence number (số thứ tự): một số xác định Message được xác nhận hoặc nack-ed. Nó tương ứng với số Message được publish.
  • multiple: đây là một giá trị boolean. Nếu false, chỉ có một Message được xác nhận / nack-ed, nếu true, tất cả các Message có số thứ tự <= được xác nhận / nack-ed.

Chúng ta có thể lấy một sequence number của một Message trước khi nó được publish thông qua phương thức sau:

long sequenceNumber = channel.getNextPublishSeqNo());

Ví dụ Publish và Confirm từng Message

Trong ví dụ này, tôi sẽ tạo một Direct Exchange, 1 channel và enable tính năng Publisher Confirm trên Channel này.

package com.gpcoder.publisherconfirm;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class SinglePublisherConfirm {

    private static final String EXCHANGE_NAME = "PublishingMessage.DirectExchange";
    private static final String QUEUE_NAME = "PublishingMessage.DirectQueue1";
    private static final String ROUTING_KEY = "batchMessage";
    private static final int NUM_OF_MESSAGE = 6;

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        // Create connection
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();

        // Create channel
        Channel channel = connection.createChannel();

        // Create direct exchange - exchange, builtinExchangeType, durable
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true);

        // Create queue - (queueName, durable, exclusive, autoDelete, arguments)
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);

        // Bind queue to exchange - (queue, exchange, routingKey)
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);

        // Enabling Publisher Confirms on a Channel
        AMQP.Confirm.SelectOk confirmed = channel.confirmSelect();
        System.out.println("Enabled published confirm: " + confirmed);

        // Handling Publisher Confirms Asynchronously
        channel.addConfirmListener((sequenceNumber, multiple) -> {
            // code when message is confirmed
            System.out.println("[Confirmed - multiple] " + multiple);
            System.out.println("[Confirmed - sequenceNumber] " + sequenceNumber);
        }, (sequenceNumber, multiple) -> {
            // code when message is nack-ed
            // Message was lost, we just print the info for debug;
            // otherwise, this case should be handled differently
            System.out.println("Not-Acknowledging for message with id " + sequenceNumber);
        });

        // Publish messages to the channel and put the ids to the queue
        for (int i = 1; i <= NUM_OF_MESSAGE; i++) {             String message = "Message " + i;             System.out.println("[Send] [" + channel.getNextPublishSeqNo() + "] " + message);             channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, null, message.getBytes());             channel.waitForConfirmsOrDie(300); // in ms         }         DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("[Received] : " + new String(message.getBody()));
        };

        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("[Canceled]" + consumerTag);
        };

        // basicConsume - ( queue, autoAck, deliverCallback, cancelCallback)
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);
    }
}

Output chương trình:

Enabled published confirm: #method()
[Send] [1] Message 1
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 1
[Send] [2] Message 2
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 2
[Send] [3] Message 3
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 3
[Send] [4] Message 4
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 4
[Send] [5] Message 5
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 5
[Send] [6] Message 6
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 6

[Received] : Message 1
[Received] : Message 2
[Received] : Message 3
[Received] : Message 4
[Received] : Message 5
[Received] : Message 6

Như bạn thấy, các Message được xác nhận từng cái một thông qua confirm callback.

Ví dụ Publish và Confirm một Batch các Message

Tương tự như trên, nhưng chúng ta yêu cầu gửi confirm callback theo batch.

package com.gpcoder.publisherconfirm;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class BatchPublisherConfirm {

    private static final String EXCHANGE_NAME = "PublishingMessage.DirectExchange";
    private static final String QUEUE_NAME = "PublishingMessage.DirectQueue1";
    private static final String ROUTING_KEY = "batchMessage";
    private static final int NUM_OF_MESSAGE = 6;
    private static final int BATCH_SIZE = 3;

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        // Create connection
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();

        // Create channel
        Channel channel = connection.createChannel();

        // Create direct exchange - exchange, builtinExchangeType, durable
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true);

        // Create queue - (queueName, durable, exclusive, autoDelete, arguments)
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);

        // Bind queue to exchange - (queue, exchange, routingKey)
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);

        // Enabling Publisher Confirms on a Channel
        AMQP.Confirm.SelectOk confirmed = channel.confirmSelect();
        System.out.println("Enabled published confirm: " + confirmed);

        // Handling Publisher Confirms Asynchronously
        channel.addConfirmListener((sequenceNumber, multiple) -> {
            // code when message is confirmed
            System.out.println("[Confirmed - multiple] " + multiple);
            System.out.println("[Confirmed - sequenceNumber] " + sequenceNumber);
        }, (sequenceNumber, multiple) -> {
            // code when message is nack-ed
            // Message was lost, we just print the info for debug;
            // otherwise, this case should be handled differently
            System.out.println("Not-Acknowledging for message with id " + sequenceNumber);
        });

        // Publish messages to the channel and put the ids to the queue
        for (int i = 1; i <= NUM_OF_MESSAGE; i++) {             String message = "Message " + i;             System.out.println("[Send] [" + channel.getNextPublishSeqNo() + "] " + message);             channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, null, message.getBytes());             if (i % BATCH_SIZE == 0) {                 channel.waitForConfirmsOrDie(300); // in ms             }         }         DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("[Received] : " + new String(message.getBody()));
        };

        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("[Canceled]" + consumerTag);
        };

        // basicConsume - ( queue, autoAck, deliverCallback, cancelCallback)
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);
    }
}

Output chương trình:

Enabled published confirm: #method()
[Send] [1] Message 1
[Send] [2] Message 2
[Send] [3] Message 3
[Confirmed - multiple] true
[Confirmed - sequenceNumber] 2
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 3
[Send] [4] Message 4
[Send] [5] Message 5
[Send] [6] Message 6
[Confirmed - multiple] false
[Confirmed - sequenceNumber] 4
[Confirmed - multiple] true
[Confirmed - sequenceNumber] 6

[Received] : Message 1
[Received] : Message 2
[Received] : Message 3
[Received] : Message 4
[Received] : Message 5
[Received] : Message 6

Như bạn thấy, trường hợp batch thì Message được xác nhận một lần có thể là 1 hay nhiều message.

  • [Confirmed – multiple] true và [Confirmed – sequenceNumber] 2 : nghĩa là đã xác nhận ok cho Message có số thứ tự <= 2.
  • [Confirmed – multiple] false và [Confirmed – sequenceNumber] 3 : nghĩa là đã xác nhận ok cho 1 Message có số thứ tự là 3.
  • [Confirmed – multiple] false và [Confirmed – sequenceNumber] 4 : nghĩa là đã xác nhận ok cho 1 Message có số thứ tự là 4.
  • [Confirmed – multiple] true và [Confirmed – sequenceNumber] 6 : nghĩa là đã xác nhận ok cho Message có số thứ tự <= 6.

Tài liệu tham khảo:

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

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

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

Xác thực trong Spring Cloud Config (Spring Cloud Config Authenticate)

Xác thực trong Spring Cloud Config (Spring Cloud Config Authenticate)

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

Thông tin cấu hình của 1 project khá quan trọng, nó chứa nhiều thông tin nhạy cảm như username/password… nên ta cần phải bảo mật nó.
Để bảo mật thông tin cấu hình từ cloud config server có 2 cách đơn giản:

  • Xác thực (dùng username/password hoặc token)
  • Mã hóa/ giải mã (mã hóa ở cloud config server, và giải mã ở cloud config client)

Trong bài này mình sẽ thực hiện theo cách thứ nhất là xác thực các request tới cloud config server.

  Bí kíp tạo website nhờ vào GitHub và Cloudflare
  Cloud Devops quan trọng như thế nào?

Xác thực trong Spring Cloud Config (Spring Cloud Config Authenticate)

Trong bài này mình sẽ sử dụng lại ví dụ trong bài trước:

Đối với project Spring Cloud Config Server

Thêm thư viện spring security vào file pom.xml:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Cấu hình security (username/password) trong file application.yml

security:
 user:
 name: admin1234
 password: admin1234

Đối với project Spring Cloud Config Client

Cấu hình username/password cho cloud config: trong file bootstrap.yml

cloud:
 config:
 uri: http://localhost:8888
 username: admin1234
 password: admin1234

Demo: start project spring-cloud-config-server

Truy cập http://localhost:8888/app/dev để xem thông tin cấu hình của ứng dụng app với profiles là dev

Xác thực trong Spring Cloud Config (Spring Cloud Config Authenticate)

Server bắt buộc phải login mới có thể xem được.

Trong trường hợp này bạn phải nhập username/password đã cấu hình ở bên trên để pass qua màn hình login.

Cách khác là bạn có thể truyền luôn username/password vào trong url: http://admin1234:admin1234@localhost:8888/app/dev. Tuy nhiên trình duyệt web ko hỗ trợ kiểu url này nên bạn có thể thử bằng 1 rest client như postman hoặc mở màn hình cmd và chạy lệnh curl:

curl http://admin1234:admin1234@localhost:8888/app/dev

Xác thực trong Spring Cloud Config (Spring Cloud Config Authenticate)

Còn đối với spring-cloud-config-client, do đã cấu hình sẵn username/password nên nó vẫn có thể lấy được cấu hình từ server như bình thường.

Xác thực trong Spring Cloud Config (Spring Cloud Config Authenticate)

Okay, Done!

Download code ví dụ trên tại đây hoặc tại: https://github.com/stackjava/spring-cloud-config-authenticate

References: https://cloud.spring.io/spring-cloud-config/reference/html/

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

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

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

Những loại virus nguy hiểm nhất mọi thời đại (Phần 1)

Những loại virus nguy hiểm nhất mọi thời đại (Phần 1)

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

Kể từ ngày virus đầu tiên xuất hiện, đến nay đã hơn 20 năm. Cũng có nhiều virus mới ra đời, dưới đây là một số loại virus nguy hiểm nhất, gây thiệt hại nặng nhất.

  Sử dụng biến Node Environment
  Nhân sự nên làm gì giữa tâm bão Coronavirus

1. CIH (1998)

Ước tính thiệt hại 20-28 triệu USD trên toàn thế giới, không tính dữ liệu PC bị phá hủy. CIH có nguồn gốc từ Đài Loan (6/1998) được nhận dạng là một trong những virus nguy hiểm và có sức tàn phá lớn nhất. CIH còn được biết đến với tên là Chernobyl vì thời điểm kích hoạt trùng với ngày xảy ra vụ nổ nhà máy nguyên tử Chernobyl. Virus này tấn công vào các file thực thi của hệ điều hành Windows 95,98 và ME, có khả năng cư trú trên bộ nhớ máy tính để lây nhiễm và các file thực thi khác.

Những loại virus nguy hiểm nhất mọi thời đại (Phần 1)

Chỉ sau một thời gian ngắn hoạt động CIH có thể ghi đè dữ liệu trên ổ cứng, biến dữ liệu trở nên vô dụng. Tuy nhiên ngày này CIH không còn nguy hiểm bởi các hệ điều hành mới như Windows XP, 2000 đã được cải tiến.

2. Melissa (1999)

Những loại virus nguy hiểm nhất mọi thời đại (Phần 1)

Ngày 26/3/1999, virus Melissa đã lây nhiễm toàn cầu, ước tính thiệt hại 300-600 triệu USD. Virus dạng kịch bản macro trong Word này đã lây nhiễm vào 15/20 chiếc máy tính doanh nghiệp trên toàn cầu. Melissa phát tán nhanh đến nỗi Intel, Microsoft và một số hãng phần mềm khác sử dụng Outlook đã buộc phải đóng toàn bộ hệ thống e-mail để hạn chế thiệt hại.

Melissa sử dụng Outlook để gửi mail đính kèm bản virus tới 50 email trong danh sách liên lạc. Email này có câu: “”Here is that document you asked for…don’t show anyone else. ;-)””. Khi nhấn vào file đính kèm virus sẽ lây vào máy tính và lặp lại chu trình phát tán.

3. ILOVEYOU (2000)

ILOVEYOU còn được biết với cái tên Loveletter và The Love Bug, một dạng Visual Basic với cái tên ngọt ngào: Lời hứa tình yêu. ILOVEYOU lần đầu tiên được phát hiện vào ngày 3/5/2000 tại Hồng Kông sau đó lây lan nhanh qua email với dòng tiêu đề ILOVEYOU cùng file đính kèm: Love-Letter-For-You.txt.vbs.

Những loại virus nguy hiểm nhất mọi thời đại (Phần 1)

Cách phát tán của ILOVEYOU cũng tương tự như Melissa. Nguy hiểm hơn nữa là virus này còn tìm tên và mật khẩu người dùng và gửi tới email tác giả. Thiệt hại ước tính là 10-15 triệu USD. Tác giả của ILOVEYOU không bị kết án do thời điểm đó Philippines không có luạt chống tội phạm máy tính.

4. Code red (2001)

Còn có tên là Bady được thiết kế với mục đích phá hủy mức lớn nhất có thể. Đây là một dạng sâu máy tính lây nhiễm trên hệ thống máy chủ, xuất hiện ngày 13/7/2001 với thiệt hại ước tính 2,6 triệu USD.

Những loại virus nguy hiểm nhất mọi thời đại (Phần 1)

Loại virus này vô cùng độc hại bởi đích đến của chúng là các máy tính chạy phần mềm máy chủ web internet information server (IIS). Code red có khả năng khai thác một lỗ hồng trong IIS. Khi đã lây nhiễm, website lưu trữ trên máy chủ sẽ hiển thị: “Hello! Welcome to http://www.worm.com! Hack by Chinese!”.

Sau đó nó sẽ tìm kiếm các máy chủ bị lỗi và lây nhiễm. Chưa đến một tuần, Code red đã lây nhiễm khoảng 400 nghìn máy chủ trên toàn thế giới.

5. SQL Slammer (2003)

Những loại virus nguy hiểm nhất mọi thời đại (Phần 1)

SQL Slammer được kích hoạt vào thứ 7 (thường là ngày nghỉ của dân văn phòng) nên thiệt hại về tiền không cao. Tuy nhiên virus này cũng đã lây nhiễm 500 nghìn máy chủ trên toàn thế giới và cũng là nhân tố tạo nên cơn bão dữ liệu ồ ạt, khiến toàn bộ hệ thống Internet của Hàn Quốc bị sập trong 12 giờ đồng hồ. SQL Slammer còn được gọi là Sapphire,kích hoạt vào ngay 25/2/2003 có tác động rất xấu đến toàn bộ giao vận Internet toàn cầu.

Virus này chỉ tìm kiếm các máy chủ, SQL Slammer là một gói dữ liệu đơn lẻ và tự gửi tới các địa chỉ IP. Nếu địa chỉ IP là một máy tính chạy bẳn SQL Server Desktop Engine chưa được vá lỗi thì chiếc máy chủ đó sẽ bị nhiếm virus ngày lập tức và tấn công các địa chỉ IP khác.

Với phương thức lây nhiễm này, Slammer có thể tấn công 75 nghìn máy tính chỉ trong 10 phút, khiến toàn bộ mạng internet bị tắc nghẽn, các router phải ngưng hoạt động.

Các bạn nhớ đón đọc phần 2 nhé.

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

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

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

Lập trình Android trên thiết bị thật qua USB cable

Lập trình Android trên thiết bị thật qua USB cable

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

Thông thường, khi lập trình android, sau khi viết code xong, bạn sẽ chạy thử ứng dụng bằng máy áo cài đặt sẵn trên IDE hoặc các máy ảo như Genymotion. Tuy nhiên chạy ứng dụng qua máy ảo khá chậm nhất là với những máy tính có cấu hình yếu

Trong bài này, mình sẽ thực hiện chạy thử các chương trình trực tiếp trên thiết bị thật.

Tuyển android không cần kinh nghiệm

  10 tài liệu lập trình Android miễn phí từ cơ bản đến nâng cao
  5 ứng dụng Android tuyệt vời dành cho Android Developer và Designer

Lập trình Android trên thiết bị thật qua USB cable

Đầu tiên bạn phải bật chế độ Developer options trên điện thoại

Mở điện thoại và chuyển đến mục Setting(Cài đặt). Sau đó, hãy chuyển đến “About phone” ( Giới thiệu về điện thoại)
Nếu Developer Options (Tùy chọn nhà phát triển) không được hiển thị trong thiết bị của bạn. Bạn cần nhấp 7 lần vào Build number để hiện Developer Options
Sau đó ra ngoài, vậy là ta đã có Developer options. Tiếp theo, bạn vào bật chế độ USB Debugging lên:

Lập trình Android trên thiết bị thật qua USB cable

Nếu có được hỏi xác thực ủy quyền cho máy tính thì chọn Always allow this computer và nhấn OK.

Và giờ chúng ta chỉ cần nhấn run project rồi sẽ hiện bảng thông báo bạn muốn chọn thiết bị nào.

Lập trình Android trên thiết bị thật qua USB cable

Nếu có tên thiết bị như trên là bạn đã cài đặt thành công máy thật connect với máy tính.

Vậy chúng ta đã cài đặt máy ảo và thiết bị thật để lập trình Android.

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

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

Xem thêm tuyển dụng ngành it hấp dẫn trên TopDev

50 keywords mà mọi lập trình viên java nên biết

50 keywords mà mọi lập trình viên java nên biết

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

Java hiện là ngôn ngữ lập trình phổ biến hàng đầu tại Việt Nam và rất nhiều sinh viên CNTT muốn theo đuổi ngôn ngữ này để phát triển sự nghiệp của mình. Có không ít khó khăn bạn cần phải vượt qua để làm chủ ngôn ngữ đầy rắc rối ấy và việc đầu tiên là hiểu những keywords – những từ khóa trong lập trình java. Việc này sẽ làm tiền đề giúp bạn trong việc tự học, tự trải nghiệm thách thức từ java.

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

Hiện nay, Java có khoảng 50 keywords và Topdev sẽ giúp bạn liệt kê hết những từ khóa này ngay sau đây:

Keyword:

Abstract: Khai báo lớp, phương thức và interface trừu tượng không có thể hiện (instance) cụ thể

Assert: Kiểm tra điều kiện đúng hay sai (hay dùng trong Unit Test)

Bloolean: Khai báo biến kiểu logic với hai giá trị: True or False

Break: Lệnh switch-case hoặc dùng để thoát khỏi vòng lặp

Byte: Các giá trị nguyên chiếm 8 bit (1byte)

Case: Trường hợp được chọn theo Switch (chỉ dùng khi được đi kèm Switch)

Catch: Dùng để bắt ngoại lệ, dùng kèm với try để xử lý những ngoại lệ nảy sinh trong chương trình

Char: Là kiểu ký tự Unicode, mỗi ký tự có 16 bit (2 byte)

Class: Dùng để định nghĩa class

Const: Không thể dùng trong java bởi nó chưa được sử dụng

Continue: Được dùng để dừng chu trình (interation) lặp hiện tại và bắt đầu chu trình kế tiếp

50 keywords mà mọi lập trình viên java nên biết

Default: Mặc định được thực thi nếu không có case nào trả về giá trị True – được dùng trong Switch case.

Do: Dùng ở  vòng lặp While

Double: Là kiểu số thực có các giá trị được biểu diển bởi dấu phẩy động 64 bit (8byte)

Else: Rẽ nhánh điều kiện ngược với If

Enum: Kiểu dữ liệu Enum – tương đối giống với kiểu dữ liệu mảng. Khác biệt ở chỗ các phần tử của kiểu này có thể bổ sung thêm các phương thức.

Extends: Dùng để định nghĩa lớp con kế thừa những thuộc tính và phương thức từ lớp cha.

Final: Dùng để chỉ ra các biến – phương thức không thay đổi sau khi đã được định nghĩa. Những phương thức final không được kế thừa và override.

Finally: Thực hiện một khối lệnh đến cùng, bỏ qua các ngoại lệ – dùng trong Try-cactch.

Float: Kiểu số thực – Các giá trị được biểu diện bởi dạng dấu phẩy động 32 bit.

For: Dùng trong vòng lặp for – Các bước lặp đã xác định từ trước.

Goto: Chưa được sử dụng

If: Là lệnh chọn theo điều kiện logic

Implements: Xây dựng 1 lớp mới cài đặt những phương thức từ interface xác định trước

Import: Dùng để yêu cầu 1 hay 1 vài lớp ở các gói chỉ định cần nhập vào để sử dụng trong ứng dụng hiện thời

Long: Là kiểu số nguyên lớn – Các giá trị chiếm 64 bit (8 byte)

Native: Sử dụng khi lập trình viên muốn dùng code bằng ngôn ngữ khác

New: Khởi tạo đối tượng

Package: Sử dụng khi xác định 1 gói sẽ chứa một số lớp trong file mã nguồn

Private: Khai báo biến dữ liệu, phương thức riêng trong từng lớp và chỉ cho phép truy cập trong lớp đó.

Protected: Dùng để khai báo biến dữ liệu – Chỉ được truy cập ở lớp cha và những lớp con của lớp đó.

Public: Dùng để khai báo biến dữ liệu, lớp – Phương thức công khai có thể tự truy cập ở mọi hệ thống.

Return: Kết thúc phương thức, trả về giá trị cho phương thức.

Short: Kiểu số nguyên ngẵn – giá trị chiếm 16 bit (2byte)

Static: Định nghĩa biến, phương thức của một lớp có thể được truy cập trực tiếp từ lớp mà không thông qua khởi tạo đối tượng của lớp.

Super: Biến chỉ tới đối tượng ở lớp cha

Switch: Sử dụng trong câu lệnh điều khiển Switch case

Synchronized: Chỉ ra là ở mõi thời điểm chỉ có 1 đối tượng hay 1 lớp có thể truy nhập đến biến dữ liệu hoặc phương thức loại đó – Thường được sử dụng trong lập trình đa luồng (multithreading).

This: Biến chỉ tới đối tượng hiện thời

Throw: Tạo một đối tượng Exception nhằm chỉ định 1 trường hợp ngoại lệ xảy ra

Throw: Chỉ định cho qua ngoại lệ nếu exception xảy ra

Transient: Chỉ định rằng nếu một đối tượng được Serialized, giá trị của biến sẽ không cần được lưu trữ

Try: Thử thực hiện cho đến khi xảy ra 1 ngoại lệ

Void: chỉ định 1 phương thức không trả về giá trị

Volatile: Báo cho chương trình dịch biết là biến khai báo volatile có thể thay đổi tùy ý trong các luồng (thread)

While: Sử dụng trong lệnh điều khiển While

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

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

Xem thêm Việc làm Java lương cao hấp dẫn trên TopDev

Hệ điều hành Android là gì? Lập trình với Android

Hệ điều hành Android là gì? Lập trình với Android

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

1. Hệ điều hành Android là gì?

Android là một hệ điều hành di dộng phổ biến nhất. Nó được chạy trên các thiết bị di động như smart phone, tablet… (điện thoại thông minh, máy tính bảng, đồng hồ thông minh)

Android là một mã nguồn mở, phát triển trên nền tảng Linux.

Hiện tại, Android được sở hữu và phát triển bởi Google.

Hệ điều hành Android là gì? Lập trình với Android

Tìm việc làm android lương cao trong tháng

2. Các phiên bản Android

Android phát triển rất nhanh, tới nay đã trải qua nhiều lần chỉnh sửa và nâng cấp với các phiên bản sau:

  •  Android 1.5 Cupcake
  • Android 1.6 Donut
  • Android 2.1 Eclair
  • Android 2.2 Froyo
  • Android 2.3 Gingerbread
  • Android 3.2 Honeycomb – Phiên bản Android đầu tiên được thiết kế cho máy tính bảng.
  • Android 4.0 Ice Cream Sandwich
  • Android 4.1 Jelly Bean
  • Android 4.2 Jelly Bean
  • Android 4.3 Jelly Bean
  • Android 4.4 KitKat
  • Android 5.0 Lollipop
  • Android 6.0 Marshmallow
  • Android 7.0 Nougat
  •  Oreo(8.0),
  •  Pie(9.0)

Hệ điều hành Android là gì? Lập trình với Android

Điều đặc biệt trong tên của các phiên bản Android đều gắn kèm với một loại đồ ăn, bánh kẹo.

  10 tài liệu lập trình Android miễn phí từ cơ bản đến nâng cao
  30+ công cụ phát triển ứng dụng Android chuyên nghiệp ( Phần 1)

3. Kiến trúc hệ điều hành android

Hệ điều hành Android là gì? Lập trình với Android

Android gồm 5 phần chính sau được chứa trong 4 lớp:

  • Nhân Linux: Đây là nhân nền tảng mà hệ điều hành Android dựa vào nó để phát triển.
  • Thư viện: Chứa tất cả các mã cái mà cung cấp cấp những tính năng chính của hệ điều hành Android.
  • Android runtime: Là tầng cùng với lớp thư viện Android runtime cung cấp một tập các thư viện cốt lỗi để cho phép các lập trình viên phát triển viết ứng dụng bằng việc sử dụng ngôn ngữ lập trình Java.
  • Android framework: Là phần thể hiện các khả năng khác nhau của Android(kết nối, thông báo, truy xuất dữ liệu) cho nhà phát triển ứng dụng.
  • Application: Tầng ứng dụng là tầng bạn có thể tìm thấy chuyển các thiết bị Android như Contact, trình duyệt…

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

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

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

Kết nối RabbitMQ sử dụng Web STOMP Plugin

Kết nối RabbitMQ sử dụng Web STOMP Plugin

Bài viết được sự cho phép của tác giả Giang Phan

Trong các bài viết trước mình đã giới thiệu với các bạn cách kết nối đến RabbitMQ sử dụng Java thông qua giao thức AMQP. Trong bài này, tôi sẽ giới thiệu với các bạn cách kết nối RabbitMQ sử dụng Javascript thông qua WebSocket.

  Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud
  Đôi chút về RabbitMQ

Web STOMP Plugin là gì?

Web STOMP plugin giúp chúng ta có thể sử dụng Javascript để kết nối đến RabbitMQ sử dụng giao thức STOMP thông qua WebSocket connection.

RabbitMQ Web STOMP sử dụng giao thức STOMP, được cung cấp bởi RabbitMQ STOMP plugin và expose (hiển thị) nó bằng WebSocket.

Để enable RabbitMQ Web STOMP plugin, sử dụng lênh sau:

rabbitmq-plugins enable rabbitmq_web_stomp

Sau khi enable, chúng ta có thể access một web socket endpoint tại context path: /ws

Chẳng hạn: http://127.0.0.1:15674/ws

Sử dụng Web STOMP Plugin

Trong ví dụ bên dưới, tôi sẽ tạo một ứng dụng Echo server, đơn giản cho phép user gửi một Message lên RabbitMQ server và subscribe để nhận Message từ RabbitMQ Server.

Giao diện chúng ta sẽ tạo như sau:

  • Box bên trái: hiển thị thông tin Message nhận được từ RabbitMQ server.
  • Box bên phải: hiển thị thông tin log message giao tiếp giữa client và RabbitMQ server thông qua websocket.
  • Một input cho phép user gửi message lên RabbitMQ server.

Kết nối RabbitMQ sử dụng Web STOMP Plugin

Để sử dụng STOMP trong Web browser context, chúng ta cần download một JavaScript STOMP library.

Link download: https://raw.github.com/jmesnil/stomp-websocket/master/lib/stomp.js

Đoạn code của chương trình như sau:

index.html

Kết nối RabbitMQ sử dụng Web STOMP Plugin

Tiếp theo, chúng ta sẽ tạo file javascript để kết nối đến RabbitMQ server, gửi và nhận message:

  • printLogDebug : hiển thị thông tin log message giao tiếp giữa client và RabbitMQ server thông qua websocket. Thông tin log sẽ được hiển thị ở box bên phải.
  • printReceivedMessage : hiển thị thông tin Message nhận được từ RabbitMQ server. Thông tin log sẽ được hiển thị ở box bên trái.
  • send : thực hiện gửi message lên RabbitMQ server.
  • subscribe: đăng ký nhận message từ RabbitMQ server.
  • bindSubmittingForm : bind sự kiện submit form (khi user nhấn enter), để lấy thông tin user đã nhập trong input và gửi Message lên RabbitMQ server.
  • onConnectCallback : phương thức này được gọi lại sau khi đã tạo Stomp Client thành công. Nó thực hiện bind sự kiện submit form, subscribe nhận message từ RabbitMQ server.
  • onErrorCallback : phương thức này được gọi lại khi tạo Stomp Client thất bại.
  • start : chạy ứng dụng, bao gồm tạo client, enable debug, tạo connection và đăng ký các callback.

Các bạn lưu ý rằng, Destination được định nghĩa trong STOMP có một chút khác biệt so với Java sử dụng AMQP. Đặc tả STOMP không quy định loại destination nào mà broker phải hỗ trợ, thay vào đó nó được xác định dựa vào giá trị của destination header trong SEND và MESSAGE. RabbitMQ STOMP hỗ trợ một số loại destination sau:

  • /exchange : SEND các khóa định tuyến tùy ý và SUBSCRIBE cho các pattern kết tùy ý.
  • /queue : SEND và SUBSCRIBE tới các hàng đợi được quản lý bởi STOMP gateway.
  • /amq/queue : SEND và SUBSCRIBE tới các hàng đợi được tạo bên ngoài STOMP gateway.
  • /topic : SEND và SUBSCRIBE tới transient và durable topic.
  • /temp-queue/ : tạo hàng đợi tạm thời (chỉ trong reply-to header).

Chi tiết các bạn tham khảo thêm tại: https://www.rabbitmq.com/stomp.html#d

rabbit-client.js

/**  * This is a RabbitMQ Web STOMP by gpcoder.com  * @see https://www.rabbitmq.com/web-stomp.html  */ // Create a destination with exchange type is topic and the routing key is gpcoder-stomp const DESTINATION = "/topic/gpcoder-stomp"; var client; var app = {     printLogDebug: function (message) {         let div = $('#logDebug');         div.append($("<code>").text(message));         div.scrollTop(div.scrollTop() + 10000);     },     printReceivedMessage: function (message) {         let div = $('#logReceivedMessage');         div.append($("<code>").text(message));         div.scrollTop(div.scrollTop() + 10000);     },     send: function(data) {         // destination, headers, body         client.send(DESTINATION, { "content-type": "text/plain" }, data);     },     subscribe: function() {         // destination, callback, headers         client.subscribe(DESTINATION, function (response) {             app.printReceivedMessage(response.body);         });     },     bindSubmittingForm: function() {         $('#first form').submit(function () {             let input = $('#first input');             let data = input.val();             app.send(data);             input.val('');             return false;         });     },     onConnectCallback: function () {         app.bindSubmittingForm();         app.subscribe();     },     onErrorCallback: function () {         console.log('error');     },     createRabbitClient: function() {         // Create STOMP client over websocket         return Stomp.client('ws://localhost:15674/ws');     },     start: function() {         // Create RabbitMQ client using STOMP over websocket         client = app.createRabbitClient(); // asign the created client as global for sending or subscribing messages                  // Enable debug         client.debug = app.printLogDebug;         // username, password, connectCallback, errorCallback, host         client.connect('guest', 'guest', app.onConnectCallback, app.onErrorCallback, '/');     } }; // Start application app.start();

Thêm một chút css cho page dễ nhìn hơn:

main.css

body {
    font-family: "Arial";
    color: #444;
}

h1, h2 {
    color: #39792e;
    font-weight: normal;
}

h1 {
    font-size: 1.5em;
    margin: 10px 20px;
}

h2 {
    font-size: 1.2em;
}

a {
    color: #39792e;
    border: 1px solid #fda;
    background: #fff0e0;
    border-radius: 3px; -moz-border-radius: 3px;
    padding: 2px;
    text-decoration: none;
    /* font-weight: bold; */
}

ul.menu {
    list-style-type: none;
    padding: 0;
    margin: 0;
}

ul.menu li {
    padding: 5px 0;
}

.box {
    width: 440px;
    float: left;
    margin: 0 20px 0 20px;
}

.box div, .box input {
    border: 1px solid;
    -moz-border-radius: 4px;
    border-radius: 4px;
    width: 100%;
    padding: 5px;
    margin: 3px 0 10px 0;
}

.box div {
    border-color: grey;
    height: 300px;
    overflow: auto;
}

div code {
    display: block;
}

#first div code {
    -moz-border-radius: 2px;
    border-radius: 2px;
    border: 1px solid #eee;
    margin-bottom: 5px;
}

#second div {
    font-size: 0.8em;
}

Bây giờ các bạn có thể chạy thử file index.html ở trên và kiểm tra kết quả.

Mở admin UI và xem thông tin Exchange, Queue được tạo:

Kết nối RabbitMQ sử dụng Web STOMP Plugin

Trên đây là một số hướng dẫn cơ bản về cách kết nối RabbitMQ server sử dụng Javascript thông qua WebSocket. Các bạn có thể tham khảo thêm cách Authentication user, cấu hình security, thay đổi host, port, … ở các liên kết bên dưới.

Tài liệu tham khảo:

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

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

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

Hướng dẫn deploy Java Project, Maven Project với Jenkins

Hướng dẫn deploy Java Project, Maven Project với Jenkins

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

Trong bài trước, mình thực hiện build 1 maven project với source lấy từ github thành 1 file .jar sau đó chạy file jar đó bằng tay.

Thực tế thì khi deploy ứng dụng, sau khi build được file .jar (hoặc là file .war.ear) thì người ta sẽ chạy file .jar đó giống như 1 service để chạy ngầm và quản lý. Hoặc với những file .war thì người ta sẽ cấu hình để sau khi build, upload file đó lên tomcat để chạy. Còn gần nhất là đang thịnh hành sử dụng docker để deploy thì người ta sẽ tạo 1 container, copy file .jar.war vào container đó và chạy.

Trong bài này mình sẽ hướng dẫn chạy file .jar tự động sau khi build giống như 1 service trên Ubuntu.

  Jenkins là gì? Build và deploy code nhanh chóng với Jenkins
  Chạy database migration khi deploy, nên hay không?

Hướng dẫn deploy Java Project, Maven Project với Jenkins.

Đầu tiên các bạn cần tạo 1 service chạy file .jar.

Ví dụ mình tạo 1 service tên là spring-boot-hello, service này thực hiện chạy file .jar ở vị trí

/home/stackjava/workspace/spring-boot-hello.jar

(Xem lại: Chạy file jar giống như một service trên Ubuntu)

Bài này mình sẽ sử dụng lại plan build trong ví dụ trước: Hướng dẫn build java project, maven project trên Jenkins

Trong phần Post Steps, chúng ta thêm các câu lệnh để chạy service (Mình dùng Ubuntu nên sẽ sử dụng Execute Shell)

Hướng dẫn deploy Java Project, Maven Project với Jenkins.

Mình sẽ sử dụng các câu lệnh để copy file .jar sau khi build vào folder /home/stackjava/workspace/spring-boot-hello.jar

Restart và kiểm tra lại status của service spring-boot-hello

echo '------- start copy jar to /home/stackjava/workspace ------------'
cp /var/lib/jenkins/jobs/spring-boot-hello/workspace/target/spring-boot-hello-0.0.1-SNAPSHOT.jar /home/stackjava/workspace/spring-boot-hello.jar
echo '------- finish copy jar -------------------------------------'
echo '------- restart spring-boot-hello service------------------'
sudo systemctl restart spring-boot-hello
echo '------- finish restart spring-boot-hello service'
sudo systemctl status spring-boot-hello

Hướng dẫn deploy Java Project, Maven Project với Jenkins.

Save lại và run lại plan build.

Lưu ý: Nếu bạn bị lỗi no tty present and no askpass program specified khi run plan build thì xem cách sửa tại đây.

Sửa lỗi sudo: no tty present and no askpass program specified

Kết quả sau khi chạy plan build:

Hướng dẫn deploy Java Project, Maven Project với Jenkins

Kiểm tra log của service spring-boot-hello:

  • sudo journalctl -f -n 100 -u spring-boot-hello

Hướng dẫn deploy Java Project, Maven Project với Jenkins

Mở brower và truy cập địa chỉ: http://localhost:8081

Hướng dẫn deploy Java Project, Maven Project với Jenkins

Trong các bài tiếp theo mình sẽ hướng dẫn deploy các project như node.js, typescript. Sử dụng docker để deploy.

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

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

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

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

Hướng dẫn xóa docker container (ví dụ docker rm)

Hướng dẫn xóa docker container (ví dụ docker rm)

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

Để xóa docker container ta dùng lệnh docker rm với cú pháp sau:

  20 trường hợp sử dụng lệnh Docker cho developer
  Cách tạo một Docker đơn giản cho Node.JS
  • docker rm [OPTIONS] CONTAINER [CONTAINER…]

Trong đó OPTIONS gồm các lựa chọn sau:

--force , -f Buộc xóa các container đang chạy
--link , -l Xóa liên kết được chỉ định
--volumes , -v Xóa các file ẩn dụng được liên kết với container

Định danh container được xóa có thể là CONTAINER ID hoặc NAMES

Ví dụ xóa docker container theo name

  • docker rm ubuntu

Hướng dẫn xóa docker container (ví dụ docker rm)

Vì container này đang chạy nên muốn xóa nó ta phải dùng thêm options -f

  • docker rm -f ubuntu

Hướng dẫn xóa docker container (ví dụ docker rm)

Okay, Done!

References: https://docs.docker.com/engine/reference/commandline/rm/

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

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

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

Thiết kế Distributed File System với GFS Phần 1

Thiết kế Distributed File System với GFS Phần 1

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

Tiếp theo chuỗi bài viết về Toàn tập về thiết kế Scalable Web Application II và Distributed cache là gì? – điều gì khiến nó trở nên mạnh mẽ?, hôm nay Kieblog hân hạnh giới thiệu chuỗi bài về Distributed File System Design (Thiết kế hệ thống phân tán lữu trữ file).

  Bài toán đồng thuận trong Distributed Systems
  Distributed cache là gì? – điều gì khiến nó trở nên mạnh mẽ?

Bài viết tập trung vào thiết kế hệ thống (Design System) cho việc lưu trữ file. Đảm bảo tính scalable cho system và sử dụng Distributed Concepts (Hệ thống phân tán).

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

1. Tiếp cận với Distributed File System

Hiện nay, hẳn không lập trình viên nào còn lạ lẫm với Google Drive, Dropbox. Đây là những hệ thống quản lý file ở quy mô lớn, scalable cho hàng tỷ người dùng, hàng triệu triệu request mỗi giây.

Việc một lượng lớn người sử dụng đặt yếu tố mở rộng (Scalable) lên hàng đầu. À nhân tiện thì bài viết này cũng có sử dụng một số phần nội dung về Google File System (GFS). Anh em có thể tham khảo thêm về GFS ở phần tham khảo của bài viết.

Để đảm bảo tính ổn định của hệ thống, như dữ liệu đã public về design thông qua GFS, ta có thể biết các hệ thống này đang thiết kế theo hướng phân tán (Distributed File System).

Nói sơ về Google File System thì nó là design cách quản lý cơ sở dữ liệu của Google. Trong GFS:

  • Customized for Google
  • Hỗ trợ lưu Large File
  • Eventual Consistency (đảm bảo tính nhất quán)
Distributed File SystemKiến trúc Google File System. Nguồn ảnh/ Source: The Google File System – Google Research

2. Chunk và Replica trong Google File System

Khi thiết kế về Google File System được chia sẻ, ta biết rõ rằng Google hỗ trợ lưu file với kích thước vô cùng lớn. Các file có thể có kích thước vào khoảng TeraByte, MegaByte.

Tất nhiên nội dung các file sẽ được chia sẻ ra thành nhiều phần và lưu trữ ở nhiều Chunk khác nhau. Không bao giờ một file có kích thước quá lớn được lưu trữ vào duy nhất một machine.

Distributed File SystemMỗi file sẽ được phân tách thành các phần có kích thước 64MB. (Số lượng chunk có kích thước 64MB tùy thuộc vào kích thước file)

Tuy nhiên nếu một phần file chỉ ở một chunk vẫn xảy ra rủi ro về file. Nếu một chunk gặp vấn đề và down, các phần để tập hợp một file có thể không đủ. Dẫn tới file bị broken.

Để giải quyết vấn đề này, mỗi part of file sẽ lưu trữ ở 3 chunk khác nhau. Nếu một chunk down, vẫn có cách để lấy file đó ở các chunk khác. Việc lưu trữ ở nhiều chunk nhỏ đảm bảo cho sự phân tán (Distributed) trong Distributed File System.

Dễ dàng scaling khi có nhiều file hoặc nội dung file lớn.

Distributed File SystemPhần nội dung số 1 sẽ lưu ở 3 chunk khách nhau là Server 1, Server 2 và Server 3.

3. Chunk Location Table System

Trường hợp file được chia thành các phần nhỏ. Mỗi lúc cần truy xuất file ở một node, ta sẽ sử dụng Location Table System.

Bảng này cho biết part đó đang nằm ở đâu?. Chunk nào?

Distributed File System

Trường hợp ở trên File được chia thành 8 phần. Các chunk id đại diện cho từng phần (tất nhiên là duy nhất Unique). Vị trí của các chunk nằm trên replica nào sẽ được ghi vào table này. Table này có thể lưu trữ vào RAM ở Master.

Trên đây là cái nhìn tổng quan nhất về Distributed File System và Google File System. Cách thức lưu trữ file lớn và những gì lưu trữ ở chunk. Tiếp theo, ở phần hai sẽ bàn về How System Work?, bổ sung một số thiết kế detail.

Anh em có thể tiếp tục đón đọc phần 2 chuỗi bài viết này ở đây.

4. Tham khảo

Thank for your time spend to read – Have nice day with your family – Happy Coding!

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

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

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

Parsing HTML sử dụng volley và jsoup

Parsing HTML sử dụng volley và jsoup

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

Hôm nay là ngày thứ 7, cuối tuần, tôi mới có thời gian thoải mái đắm chìm trong một vài bài nhạc Trịnh du dương,ngọt ngào  cùng nhấm nháp thứ chất lỏng đen sì , chát đắng  sặc mùi hóa chất mà người ta vẫn hay kháo nhau bằng cái tên rất mĩ miều “cafe” .Chết lảm nhảm rồi!!!

  5 bước tìm hiểu sơ lược thành phần một web HTML động
  Cách để tạo một Switch trên iPhone bằng HTML và CSS

Đây là một bài chia sẻ. Chuẩn đấy! Mặc dù nó được tôi viết (chính xác là đánh máy), nhưng nó chỉ là một bài chia sẻ . Chắc chắn không phải là một giáo án hay đại loại thế, đừng nhầm! Giáo án thuộc một phạm trù gì đó dành cho nhà giáo đáng kính , hay các expert cao quý .Còn tôi, đơn thuần là một anh chàng đang trong tuổi ăn , tuổi học loay hoay tập code kể lại mấy hoạt động  testing với cái gọi là parsing HTML. Thế nên, xin nhắc lại lần nữa: Đây, là một bài chia sẻ :)) .Ấy lại lảm nhảm rồi

Nhưng bắt đầu từ đâu đây? Htmljsoup

Thực ra thì cái nào cũng quan trọng với bài này, khi bạn click vào link này thì chắc là bạn có lướt qua một trong những khái niệm trên rồi nhỉ .Nếu không thì các bạn vào từng cái để tìm hiểu đã nhé

Thôi , có vẻ hơi lan man . Chúng ta vào phần chính, à mà quên. nhược điểm của việc bóc tách theo dạng này là rất tốn băng thông nhé vì phải download cả file html, và app rất dễ tèo (app phụ thuộc hoàn toàn vào web theo một cách hoàn toàn bị động)

Thôi zô nào

Cấu trúc của project :

1   Interfaces

2  IHTMLParser

3  IAsyncCallback

Tiếp theo là thư viện sử dụng , các bạn nhớ add đầy đủ nhé

Chúng ta sẽ xử lý Networking thông qua thư viện volley.Nói về volley thì các bạn cũng biết ưu điểm của nó là gì rồi,Các bạn vào đây tìm hiểu thêm

Màn khởi động thế là ổn rồi :).Chúng ta đến với class đầu tiên

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

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

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

Các mẫu báo cáo tháng HR cần theo dõi trong công tác nhân sự

mẫu báo cáo tháng hr
mẫu báo cáo tháng hr

Mẫu báo cáo tháng HR cần là những báo cáo được quan tâm nhằm đánh giá xác lập cơ sở; đánh giá tình hình phát triển của công tác nhân sự suốt một tháng vừa qua. Sẽ là một thiếu sót lớn nếu bạn lỡ bỏ qua những mẫu báo cáo tháng HR này.

Ngoài ra, nội dung chính báo cáo HR còn có ý nghĩa quan trọng trong việc đánh giá chất lượng; tác động lớn đến chiến lược tiếp theo của toàn quy trình. Tính ổn định; mức độ hiệu quả đều được thể hiện rõ qua mẫu report HR. Đây cũng là cơ sở quan trọng để phòng nhân sự tối ưu hóa quy trình làm việc; nhận ra những sai sót, các vấn đề còn tồn động để tìm ra giải pháp khắc phục kịp thời. 

Cùng TopDev điểm qua 4 loại báo cáo quan trọng trong công tác quản trị nhân sự; mà bắt buộc bất kỳ HR nào cũng sẽ cần nắm bắt.

Báo cáo nhân sự liên đến sự chuyển biến nhân sự

Mẫu report HR này có mục đích chính là theo dõi những biến đổi trong quá trình tiếp nhận, tổ chức; hoặc có liên quan tới  số lượng nhân sự của công ty. 

mẫu báo cáo tháng hr
mẫu báo cáo tháng hr

ăn cứ theo các tiêu chí gồm: thâm niên, thời gian, vị trí,.. Thông qua đó biết được sự tăng giảm của nhân viên.

Cụ thể mẫu báo cáo tháng HR gồm có:

Báo cáo biến động theo thâm niên

Liệu bạn có biết được tỷ lệ thay đổi, biến động; và có sự xác định rõ giữa các nhóm nhân viên hay không? Tất cả sẽ được biểu hiện rõ qua mẫu báo cáo tháng HR này. Thông qua mẫu report HR này, ban quản trị nhân sự có thể tìm ra các nguyên nhân căn bản nhất một cách chính xác. Từ đó, làm cơ sở quan trọng để thiết lập ra những giải pháp phù hợp nhất với tình hình hiện tại.

Mẫu report HR này được dùng để chia các nhóm thâm niên (nhóm < 01 tháng, 03 tháng, 06 tháng, 12 tháng, 24 tháng, nhỏ hơn hoặc lớn hơn 36 tháng).

Mẫu report HR biến động theo thời gian

Nội dung chính báo cào HR này xoay quanh việc nhận định; đánh giá từ tổng quan đến chi tiết quá trình. Ban quản trị nhân sự có thể nhìn ra được khoảng thời gian nào là thời điểm các nhân viên có sự dịch chuyển về công việc nhiều nhất. Đây được gọi là thời điểm nhảy việc. Và dựa trên những số liệu thực tế, thời gian này tập trung phân bổ chủ yếu rõ rệt nhất là vào khoảng tháng 1 và tháng 2 dương lịch. 

  Nhân sự là gì? Vai trò và các vị trí công việc của HR
mẫu báo cáo tháng hr
mẫu báo cáo tháng hr

Theo các báo cáo nhân sự từ các tập đoàn lớn thì đây cũng chính là thời gian mà các công ty có nhiều sự biến động mạnh mẽ nhất về sự thay đổi nhân sự (sau khi nhận lương thưởng Tết xong).

Lúc này, phòng Nhân sự sẽ ngồi lại với nhau để tìm ra các yếu tố quyết định nghỉ việc của  từng người. Đồng thời, chuẩn bị nguồn ứng viên cần để thay thế vị trí đó. Mẫu báo cáo tháng HR này thông thường sẽ được chia theo tỷ lệ tháng/năm. 

Tính biến động từ báo cáo này cũng được thể hiện rất rõ thông qua thực tế. Khi dễ dàng thấy được từ tháng 01 đến tháng 08, tỉ lệ biến động nghỉ việc tăng dần. Chính số liệu và khoảng thời gian cụ thể, các công ty sẽ bắt đầu đánh giá; tìm ra nguồn cơn tạo ra sự thay đổi này. Đồng thời, lên kế hoạch cho những thay đổi có thể diễn ra trong giai đoạn mới. 

Báo cáo dựa theo biến động vị trí công việc

Đây là loại báo cáo tháng HR cung cấp cái nhìn tổng quan & khách quan theo tỷ lệ biến động lớn. Công việc chủ yếu của trưởng bộ phận các phòng ban là cần tập trung tìm ra nguyên nhân; cùng các giải pháp nhằm cải tiến hiệu suất. Nội dung chính báo cáo HR này thường chia thành các nhóm tương ứng với những vị trí chức vụ giống nhau.

  Nhân sự là gì? Vai trò và các vị trí công việc của HR

Báo cáo chấp hành các quy định công, ca

Mẫu báo cáo tháng HR nhân sự thể hiện tính tổng quan việc tuân thủ thời gian làm việc; chấp hành quy định đối với từng bộ phận; cũng như toàn công ty vận hành theo cơ cấu trực tuyến chức năng. Từ cái nhìn chung ấy, HR sẽ có cơ sở phân tích; đồng thời chỉ ra tất cả các vấn đề vi phạm quy trình một cách có dẫn chứng (thông qua sự biến động về số liệu); và công tác quản lý của công ty. 

Ý thức của mỗi nhân viên cũng được xem là yếu tố quan trọng. Vì nó có thể dẫn đến nhiều thay đổi trong công tác và quy trình tuyển dụng nhân sự.

Mẫu report HR cho thấy mức độ hiệu quả quá trình sử dụng lao động

Đây là mẫu báo cáo tháng HR tiêu chuẩn nhất. Và nó được đánh giá là một trong những báo cáo quan trọng. Mẫu report này giúp ban lãnh đạo nhận thấy được hiệu suất của sự tác động đến hoạt động kinh doanh. Đồng thời giải đáp được cơ cấu vị trí chức vụ, lương, trình độ nhân viên xem có tương thích với khả năng thực sự; trình độ và tiềm năng phát triển của họ hay không.

Đặc điểm về nội dung chính báo cáo HR:

– Xét dựa trên phương diện mục tiêu; tính đặc thù tương thích với từng loại hình kinh doanh để tạo ra báo cáo cụ thể.

– Theo phân tích, so sánh từ chính bộ phận hoặc doanh nghiệp theo thời gian, ngày tháng, quý, năm. 

– Mẫu báo cáo tháng HR này thường dùng để so sánh hiệu suất giữa bộ phận, đơn vị này với các bộ phận hoặc là đơn vị khác.

Điều cần lưu ý khi xây dựng mẫu báo cáo tháng HR này  thường căn cứ theo các chỉ tiêu:

  • Số lượng sản phẩm/ định biên nhân sự
  • Số lượng sản phẩm / tổng chi phí tiền lương

Việc tối ưu hiệu quả mà mẫu report HR mang lại rất quan trọng. Các bộ phận cần được chia sẻ kết quả của quá trình sản xuất kinh doanh trong từng đơn vị một cách cụ thể. Khi có những thông tin xác thực; các số liệu thực tế về quy trình phát triển doanh nghiệp, việc thiết lập báo cáo và sự phân tích, đánh giá sẽ có cơ sở và đạt được hiệu quả cao hơn.

Mẫu report HR tuyển dụng

Khi nhắc tới các loại báo cáo quan trọng của nhân sự không thể không nhắc tới báo cáo hiệu quả tuyển dụng. Trong loại báo cáo này thì nhân sự cần phải nêu rõ được hiệu quả tuyển dụng; so sánh chuẩn xác được những kênh đem tới nguồn ứng viên thích hợp với doanh nghiệp.

mẫu báo cáo tháng hr
mẫu báo cáo tháng hr

Báo cáo hiệu quả tuyển dụng gồm 2 loại: Công tác tuyển dụng và bảng đánh giá hiệu quả với từng nguồn tuyển dụng.

Lời kết

Mẫu báo cáo tháng HR đóng một vai trò quan trọng đối với định hướng phát triển lâu dài cho tổ chức/doanh nghiệp. 4 loại mẫu report HR vừa kể trên có tính thông dụng cao. Nó là các mẫu báo cáo mà ai trong lĩnh vực HR nhân sự cũng cần phải nắm. Mong rằng, bài viết đã cung cấp cho mọi người những thông tin bổ ích về các loại báo cao tháng HR. Từ đó, lựa chọn và sử dụng cho phù hợp; cũng như thiết lập một cách toàn diện quá trình báo cáo HR một cách tốt nhất.

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

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

Là framework? Hay là library?

Là framework? hay là library?

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

Hôm nay mình nghe bài nói chuyện giữa anh Kyle Simpson (tác giả You Don’t Know JS) và Jeff từ Software Engineering Daily [1]  Nếu các bạn đang hỏi là: Ơ, tự nhiên lòi đâu ra cái vụ nghe podcast nữa? Thì podcast là một phong trào mới nổi trong cộng đồng developer, và tính cả thời gian đi làm lẫn đi về của mình thì một ngày tốn tầm 3, 4 tiếng lái xe, nên nghe podcast/audio book để tận dụng thời gian “chết” là một giải pháp vừa hiển nhiên vừa chỉ có lợi.thì thấy một ý kiến khá là đáng quan tâm của anh Kyle về cách phân biệt giữa library và framework, note lại kẻo quên.

  10 Frameworks tốt nhất hiện nay cho PHP
  12 Packages và Libraries của Go cực kì mạnh mẽ mà bạn cần phải biết

Đầu tiên, anh Kyle đưa ra một ví dụ về việc lái xe: Giả sử bạn lái xe, và muốn đi từ điểm A tới điểm B, mà bạn không biết đường.

  • Cách đơn giản nhất, đó là mở ngăn kéo lấy ra một tấm bản đồ, nhìn vô đó để tìm đường đi, tấm bản đồ bằng giấy, và bạn phải tự tìm đường bằng cách hình dung ra con đường. Tấm bản đồ là một công cụ giúp bạn tìm đường đi, nhưng tự thân nó không đưa ra bất kì ý kiến hay chỉ dẫn nào cho bạn.
  • Ở một cấp độ khác cao hơn, chúng ta có các thể loại thiết bị kết nối GPS, đưa ra các gợi ý và hướng dẫn để chúng ta đi từ điểm này đến điểm khác, như Google Maps trên điện thoại. Tuy nhiên, nếu Google Maps biểu bạn rẽ trái, mà bạn lại quẹo phải, thì cũng không sao. Bạn luôn luôn có sự lựa chọn là nghe theo hoặc không nghe theo các ý kiến chỉ dẫn đó.
  • Cấp độ cao hơn nữa, đó là xe tự lái, bạn ngồi lên xe, ra lệnh cho nó chạy từ chỗ này đến chỗ kia, và nó sẽ tự tìm đường để đưa bạn đến nơi cần đến, có nghĩa là bạn đi theo nó, và bạn không có sự lựa chọn nào khác  Chỉ là đại khái thôi, thực ra xe tự lái thì bạn vẫn có thể can thiệp được vào việc nó lái, và đó là luật.ngoài việc nằm im và hưởng thụ ngồi yên cho nó lái.
■  Đọc tới đây hẳn các bạn cũng đã hình dung ra được thế nào là framework và library rồi đúng không? đọc tiếp đi.

Ở trên là 3 cấp độ đại diện cho 3 cách phân loại: libraryframework và platform, lần lượt dựa trên mức độ opinionated của chúng.

  • Library là các loại công cụ chỉ đơn thuần là công cụ, không đưa ra bất kỳ ý kiến hay chỉ dẫn nào để bạn phải làm theo, bạn có thể tùy ý sử dụng và tùy biến nó theo cách của bạn. jQuery, underscore, lodash là các ví dụ về library, chúng chỉ cung cấp cho chúng ta các công cụ cần thiết để tùy ý lựa chọn và sử dụng chứ ta không cần phải theo một quy tắc gì.
  • Framework là các công cụ opinionated, nó đưa ra các quy tắc và hướng dẫn để chúng ta phải tuân theo, tuy nhiên nếu không theo thì cũng chả chết ai. Angular là một framework, vì nó bắt bạn code theo quy tắc của nó (từ cách đặt tên, cho tới cách tổ chức cấu trúc dự án, service, module, cách viết directives…). React thì nằm đâu đó giữa framework và library vì nó không bắt buộc chúng ta phải tuân theo một quy cách nào, mỗi người có một cách sử dụng React riêng, nhưng vẫn phải tuân theo một số quy tắc mà nó đưa ra (ví dụ các lifecycle handler của một component, và bạn có thể tùy ý setState hoặc xài Redux,…).
  • Platform là các công cụ cực kì opinionated Cũng có người định nghĩa platform theo nghĩa rộng hơn, là bao gồm cả hệ điều hành, phần cứng, nơi mà các ứng dụng, framework chạy. Tuy nhiên cách định nghĩa này có vẻ không liên quan đến platform trong bài viết.bạn phải tuân theo hoàn toàn mọi quy tắc mà nó đưa ra, làm khác đi thì không được. Ví dụ WordPress nằm ở giữa khoản framework và platform, một bộ theme phải có các thành phần này kia, phải có function.php (phải ko ta, lâu rồi không code PHP), .NET Framework là một platform. PhoneGap là một platform.

Notes

  1. Podcast: JavaScript Concurrency with Kyle Simpson 

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

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

Tôi đã học được những gì từ dự án đầu tiên của mình?

kinh nghiệm lập trình
Tôi đã học được những gì từ dự án đầu tiên của mình?

Tác giả: Jessica Wilkins

Sau bốn tháng dài viết code, nghiên cứu, tìm hiểu mọi thứ và tự hỏi liệu bao giờ nó hoàn thành, cuối cùng tôi đã được triển khai trang web đầu tiên của mình. Đó không phải là một con đường dễ dàng, nhưng kết quả cuối cùng rất xứng đáng. Bên cạnh đó, tôi cũng rút ra được nhiều kinh nghiệm lập trình hữu ích cho mình.

kỹ năng lập trình
Kỹ năng lập trình sẽ được cải thiện sau nhiều dự án

1. Tôi có thể làm được điều đó không?

Vào tháng 6 năm 2020, căng thẳng chủng tộc ở mức cao chưa từng thấy vì những sự kiện xung quanh cái chết của George Floyd. Kết quả là, điều này đã tạo ra một cuộc trò chuyện về sự thiếu đa dạng và đại diện của các nhóm thiểu số trong tất cả các ngành.

Tôi đã có rất nhiều bạn bè liên hệ với tôi và hỏi thông tin về các nhà soạn nhạc da đen trong quá khứ và hiện tại với hy vọng âm nhạc của họ được biểu diễn thường xuyên hơn. Để đáp lại điều này, tôi quyết định bắt đầu chuỗi video Youtube Black Excellence giới thiệu những nhà soạn nhạc da đen thành công.

  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java
  10 Kỹ năng quan trọng cần có của Front-end để tìm công việc dễ dàng hơn

Bộ truyện đã thành công vang dội và một ý tưởng mới đã ra đời. Điều gì sẽ xảy ra nếu có một trang web tên là Black Excellence Music Project? Nó có thể là một trang web giáo dục với hồ sơ, trò chơi, âm nhạc và rất nhiều thứ khác. Nhưng có một vấn đề lớn hơn: ai trên thế giới sẽ tạo ra thứ này?

Tôi chỉ mới bắt đầu hành trình viết code được vài tuần, chưa có nhiều kinh nghiệm lập trình và tôi không nghĩ mình đủ khả năng để xây dựng một thứ như thế này. Vì vậy, tôi quyết định đặt nó vào ổ ghi phía sau và tiếp tục với việc học của mình.

2. Bây giờ hoặc không bao giờ

Vài tháng sau, tôi bắt đầu suy nghĩ nhiều hơn về dự án. Tôi đã nghĩ về các trò chơi có thể có, các nhà soạn nhạc nổi bật và các tính năng thú vị khác. Nhưng tôi vẫn còn do dự khi bắt đầu vì tôi cảm thấy mình chưa sẵn sàng. Tôi chỉ biết HTML, CSS và một chút JavaScript. Nhưng tôi nhận ra một điều rằng: bây giờ hoặc không bao giờ.

Vậy nên, mặc dù sợ hãi và do dự, tôi quyết định sẽ bắt đầu.

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

3. Bắt đầu với Git và Github

Lần đầu tiên tôi mở tài khoản GitHub của mình vào tháng 6 năm 2020, khi tôi quyết định học cách viết code. Tôi đã không thực sự làm bất cứ điều gì với nó trong vài tháng trước khi bắt đầu dự án này. Cảm giác mơ hồ của tôi về GitHub là bạn có thể lưu code của mình và mọi người có thể nhìn vào nó. Vì vậy, tôi quyết định đã đến lúc thực sự tìm hiểu về GitHub và bắt đầu làm việc với dòng lệnh.

Sau khi xem một vài hướng dẫn, tôi đã tạo thành công repo đầu tiên của mình và đẩy lên GitHub. Tôi rất vui vì mình đã có thể làm được gì đó, nhưng bây giờ tôi phải tiếp tục như thế nào? Tôi sẽ làm cái gì tiếp theo?

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

4. Chỉ với HTML

Tôi đã có tất cả những ý tưởng này nhưng hoàn toàn không biết bắt đầu từ đâu. Tôi có bắt đầu với trò chơi xây dựng không? Tôi có xây dựng mô hình thiết kế không? Mọi thứ nhanh chóng bắt đầu trở nên choáng ngợp và tôi không biết phải làm gì tiếp theo. Vì vậy, tôi quyết định chỉ bắt đầu với một trang HTML đơn giản.

Tôi cố gắng tạo một số trang HTML cho hồ sơ nhà soạn nhạc và lo lắng về việc tạo kiểu cho chúng sau này. Cách tiếp cận này làm tôi thấy yên tâm hơn và dẫn đến một khởi đầu rất hiệu quả cho dự án.

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

5. Chọn bảng màu phù hợp

Tôi muốn chọn một bảng màu phù hợp với chủ đề. Tôi muốn một thứ gì đó êm dịu nhưng có tiềm ẩn sức mạnh đằng sau nó. Sau một số nghiên cứu, tôi quyết định chọn màu tím. Màu tím thường được xem là đại diện cho sự sang trọng và trí tuệ.

Tôi nghĩ đây sẽ là sự lựa chọn hoàn hảo cho những nhà soạn nhạc da đen đã có những đóng góp đáng kể cho nghệ thuật.

kinh nghiệm lập trình
Để hoàn thành việc build một trang web cần sự phối hợp của rất nhiều yếu tố

6. Có những cách nào để tôi sáng tạo game?

Đến lúc này, tôi đã có một vài trang HTML và một số style cơ bản. Và đã đến lúc bắt đầu viết code cho một số trò chơi. Tôi nghĩ sẽ rất tuyệt nếu có một vài trò chơi mà cả trẻ em và người lớn đều thích. Lần đầu tiên tôi bắt đầu với việc vạch ra cách các trò chơi sẽ hoạt động. Sau đó, tôi bắt đầu giải quyết từng chức năng một. Tôi đã nghiên cứu rất nhiều và mắc rất nhiều sai lầm nhưng cuối cùng tôi cũng bắt được chúng.

// this is for the tour and local gig functions
function performanceOutcomes() {
  shuffle(gigResponses);
  if (randomMsg === 'You were late to the gig and not allowed to perform.' || randomMsg === 'You were mugged outside after the gig and they took all of your money.') {
    message.innerHTML = randomMsg;
    money += 0;
    earnings.innerHTML = `Total earnings: $ ${money}`;
  } else {
    message.innerHTML = randomMsg;
    money += 5;
    earnings.innerHTML = `Total earnings: $ ${money}`;
  }
}

7. Sắp xếp thông tin như thế nào?

Sẽ có rất nhiều phần chuyển đến trang web vì vậy tôi cần phải thông minh trong việc quản lý tất cả các tệp này. Tôi luôn ý thức về việc chọn các tên tệp và thư mục mô tả cần ngắn gọn để có thể dễ dàng tìm thấy chúng.

Tôi cũng gặp phải vấn đề có nhiều bảng định kiểu. Vì tôi đang sử dụng lại rất nhiều kiểu giống nhau, nên sẽ hợp lý hơn khi chỉ có một biểu định kiểu chính và liên kết nó với tất cả các trang HTML.

Xem thêm các việc làm tuyển dụng Tester chưa có kinh nghiệp hấp dẫn tại TopDev

8. Dự án cơ bản đã hoàn thành

Vào cuối tháng 1 năm 2021, trang web cuối cùng đã sẵn sàng onboard. Tôi quyết định liên hệ với Nicholas Carrigan, người kiểm duyệt và nhà phát triển freeCodeCamp. Anh ấy có một dịch vụ cho các phiên đánh giá code trên trang web của anh ấy và tôi muốn anh ấy check code của mình. Buổi đánh giá rất có giá trị và tôi đã học được rất nhiều về cách làm cho trang web trở nên tốt hơn nữa.

9. Nhưng sự thật khi xuất bản trang web thì…

Không có thanh điều hướng. Không có chân trang. Không có CSS.

Tại sao điều này lại xảy ra?

Mọi thứ đều ổn khi tôi thử nghiệm nó tại địa phương. Sau nhiều giờ mày mò và nghiên cứu, cuối cùng tôi đã tìm đến sự giúp đỡ. Tôi đã nhắn tin cho Nicholas và giải thích vấn đề. Anh ấy check code và giải thích rằng có vấn đề với đường dẫn tệp của tôi và chỉ cho tôi cách khắc phục. Tôi cảm thấy nhẹ nhõm khi biết giải pháp cho vấn đề của mình và có thể thực hiện tất cả các thay đổi cần thiết.

  <script src="landing-page-nav.js"></script>
    <script src="landing-page-footer.js"></script>
    <script src="index.js"></script>

10. Lời khuyên cho người mới bắt đầu

Tôi đã học được rất nhiều điều khi xây dựng dự án này và chắc chắn có một phần thăng trầm. Nhưng cuối cùng, tôi rất hạnh phúc với kết quả mình đã đạt được. Nhất là với những kinh nghiệm lập trình tôi đúc kết được.

Những kinh nghiệm lập trình đó là gì?

Nếu bạn có ý tưởng cho một dự án, chỉ cần bắt đầu. Đừng đợi cho đến khi bạn sẵn sàng. Xây dựng nó theo cách tốt nhất mà bạn biết cách và triển khai nó. Nó là hoàn toàn tốt nó không phải là hoàn hảo hoặc đánh bóng. Chỉ cần tiếp tục xây dựng và học hỏi.

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

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

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

Phần 1 – Học AWS cơ bản: Quán Net

Phần 1 - Học AWS cơ bản: Quán Net

Bài viết được sự cho phép của tác giả Trần Khôi Nguyên Hoàng

Chắc chắn trong đời của các bạn thì đã một lần trốn học đi chơi Net. Và mình cũng thế, mình cũng có một tuổi thơ ăn dầm nằm dề ở quán các quán net cỏ ngày xưa. …
Chính vì thế, mình sẽ mượn hình ảnh của quán Net để nói một cách tổng quát các khái niệm của Amazon Web Services (AWS), giúp các bạn có một cái nhìn tổng quát hơn về AWS.

Phần 1 - Học AWS cơ bản: Quán Net

Quán Net Amazon

Tưởng tượng rằng công ty A muốn mở một chuỗi các cửa hàng kinh doanh quán Net với cấu hình khủng. Vì công ty A giàu vcl nên công ty A muốn mở chuỗi cửa hàng Net trên toàn bộ thế giới. Cứ một quốc gia sẽ có một quán Net ở mỗi thành phố lớn ở quốc gia đó.
Quán Net của ông ty A thì to vcl, mỗi quán lại có vài nghìn máy cấu hình khủng, đủ cho các Skys cày view cho sếp hay là đua rank LOL.

  AWS, Azure và Google Cloud là gì? Chứng chỉ nào tốt nhất cho sự nghiệp của bạn?

  Công nghệ Cloud: Bối cảnh sử dụng Cloud & kinh nghiệm làm việc với AWS, IaC

Cũng như bao quán Net khác, quán Net của công ty A cũng đánh số lên mỗi máy: Máy 1, Máy 2, Máy 3, để nhân viên dễ dàng quản lý và khách hàng cũng dễ dàng tìm được máy mà mình thích hơn.
Tuy nhiên, quán Net này lại không có nhân viên kỹ thuật, chính vì thế, khách hàng tới chơi Net phải tự chuẩn bị sẵn bộ cài Window (hoặc bất cứ hệ điều hành nào) để cài lên máy, sau đó thì mới làm gì thì làm.
Trước khi đi vào quán Net thì khách hàng phải đi qua bộ phận bảo vệ của quán, để dảm bảo là các bạn không mang hung khí vào quán hay giúp các bạn trẻ né những pha gank thần thánh đến từ phụ huynh.

Vậy thì nó liên quan gì đến AWS?

Thật ra thì nó có liên quan cả đấy. Nếu như các bạn thay:

  • Công ty A = Amazon
  • Quán Net = Amazon Web Services
  • Mỗi quốc gia = Region
  • Mỗi thành phố = Availability Zones
  • Máy tính = EC2
  • USB chứa hệ điều hành = AMI
  • Máy số 1 = Elasctic IP
  • Bảo vệ = ASG

Thì các bạn đã nắm được sơ sơ cách hoạt động và các khái niệm cơ bản của AWS rồi đấy

Quay lại với AWS

Thông qua ví dụ ở trên thì mình sẽ nói rõ hơn về các khái niệm cơ bản nhất của AWS nhé.

Region

Region của AWS ở đây thì nó giống hệt như các quốc gia ở ví dụ về quán Net của mình ở trên. Amazon sẽ đặt máy chủ của họ ở rất nhiều quốc gia và khu vưc khác nhau trên toàn thế giới. Ở thời điểm hiện tại thì sẽ có tổng cộng là 22 quốc gia mà Amazon chọn mặt gửi vàng để đặt máy chủ.
Điều này có nghĩa là khi mua dịch vụ của AWS thì nên chọn khu vực nào đó phù hợp với nhu cầu của mình. Ví dụ ở Việt Nam thì nên chọn khu vực là Singapore vì máy chủ ở đây gần với Đông Lào nhất, nên tốc độ sẽ nhanh hơn nhiều.

Phần 1 - Học AWS cơ bản: Quán Net

Availability Zones (AZ)

Cũng như ở trên, cứ một một quốc gia thì Amazon sẽ tiếp tục đặt máy chủ của mình ở mỗi khu vực khác nhau. Ví dụ như ở Amazon chọn Singapore làm chỗ đặt máy chủ thì Amazon sẽ đặt vài cái server khác nhau ở mỗi một chỗ khác nhau để đảm bảo an toàn. Lỡ khủng bố nó bắn bể server ở một chỗ thì còn vài chỗ khác backup. Mỗi một cái máy chủ sẽ gọi là một Availability Zones (AZ).

Phần 1 - Học AWS cơ bản: Quán Net

EC2

Ở một một cái máy chủ, thì Amazon cho phép mình thuê các Instance trên các máy chủ đó. Nó giống hệt như mình thuê một cái máy tính như ví dụ ở trên của mình. Không khác gì cả. Cái máy tính mình thuê này có tên là EC2, là một máy tính ảo mà Amazon cho mình.
Vì là máy tính nên mỗi cái máy tính sẽ có cấu hình khác nhau, tùy vào nhu cầu lựa chọn của mình. Các bạn cứ lên thẳng trang chủ của AWS mà xem cấu hình của từng con rồi chọn con nào phù hợp với nhu cầu của mình.
Thường thì nếu là nhu cầu học hành thì dùng con t2.micro là ok rồi. Con này nó cho xài free luôn.

Phần 1 - Học AWS cơ bản: Quán Net

Amazon Machine Image (AMI)

Sau khi có máy tính rồi, thì việc tiếp theo là phải cài đặt hệ điều hành cho nó. Cái này thì anh em cài Win dạo chắc biết hết. Kiểu gì cũng phải tải bộ cài về rồi dùng USB tạo boot rồi đem đi cài Win dạo được chứ.
Giống y vậy, thì bộ cài ở đây gọi là AMI. Amazon cho mình chọn là mình muốn cài cái gì luôn, tùy vào nhu cầu thì chọn cái để cài thôi. Ví dụ như mình có thể cài Windows, Ubuntu, Redhat, hay Fedora. Cái gì cũng được. Lúc mình thuê EC2 là nó cho mình chọn cả. Mình cũng có thể build riêng hệ điều hành của mình rồi cài lên cũng được nốt.
Amazon có cung cấp một AMI mà mình nghĩ là hay xài nhất là Amazon Linux. Đó về cơ bản là một hệ điều hành Linux với một số tool được Amazon cài sẵng. Mình dùng thằng này để học. Mấy thằng khác thì mình không có nhiều kinh nghiệp lắm.

Elasctic IP

Khi vào một quán Net thì mỗi một máy có một địa chỉ nhất định. Ví dụ như máy 1, máy 2, máy 2. Thì tương tự, khi bạn thuê một cái EC2 thì Amazon sẽ cung cấp cho bạn một cái địa chỉ, gọi là IPv4.
Tuy nhiên, cái địa chỉ này nó sẽ thay đổi mỗi lần bạn tắt EC2 hay khởi động lại EC2. Chính vì thế, Amazon cung cấp cho bạn một cái địa chỉ cố định và không bao giờ thay đổi, gọi là Elasctic IP. Cơ mà cái này phải tốn tiền để có được, nên thường thì các trang Web vừa và nhỏ không cần dùng thằng này làm gì cả. Thường thì người ta sẽ dùng DNS để trỏ qua IPv4 một cách tự động mà không cần dùng đến Elasctic IP.

Amazon Security Group (ASG)

Amazon Security Group giống hệt như bảo vệ của quán Net vậy. Bảo vệ sẽ kiểm soát toàn bộ các khách hàng đi ra đi vào quán Net. Cũng như Amazon Security Group sẽ kiểm soát toàn bộ các kết nối đi vào và đi ra instance. Mặc định, khi các bạn tạo một instance thì một ASG được tạo và block tất cả các kết nối ngoài vào và chấp nhận các kết nối từ trong đi ra.
Ví dụ như khi mình tạo một Instance và trong SG mình cấu hình chỉ cho port 22 (SSH) đi từ ngoài vào, thì chỉ có các kết nối bằng port 22 mới có thể đi vào EC2, còn lại sẽ bị block sạch.

Phần 1 - Học AWS cơ bản: Quán Net

Kết luận

Trên đây là các khái niệm cực kỳ cơ bản và đơn giản AWS. Mình không đi sâu vào tính năng của mỗi phần (Mình chưa học kỹ) nhưng cũng đủ để cho các bạn hình dung sơ sơ được AWS nó tròn méo ra sao. Phần sau mình sẽ nói tiếp đến các khái niệm khác như Load Balancer hay Auto Scaling Group nhé.

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

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

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

Giới thiệu Scene và Segue trong Swift

Giới thiệu Scene và Segue trong Swift

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

I. Scene trong Swift

Scene là các màn hình do View Controller quản lý và làm việc hiển thị giao diện người dùng.Vì vậy khi bạn tạo Scene cũng chính là bạn tạo đối tượng View Controller vào trong Storyboard.

+Cách tạo Scene:

-Các bạn tìm kiếm View Controller trong ô tìm kiếm và kéo vào Storyboard vừa tạo.

Giới thiệu Scene và Segue trong Swift

Và đây chúng ta đã có một Scene

Giới thiệu Scene và Segue trong Swift

-Tiếp theo tạo class kế thừa từ UIViewController để quản lý màn hình vừa tạo.

Giới thiệu Scene và Segue trong Swift

Để Xcode hiểu class vừa tạo là file quản lý màn hình thì chúng ta phải khai báo ở đây.

Giới thiệu Scene và Segue trong Swift

Để màn hình nào đó chạy đầu tiên thì bạn cần cài đặt trong Storyboard.

Các bạn hãy click vào checkbox Is initial View Controller.

Giới thiệu Scene và Segue trong Swift

Tìm việc làm code swift lương cao không cần kinh nghiệm cho bạn tại đây

II. Segue trong Swift

1. Segue là gì?

Segue có tác dụng là chuyển tiếp giữa các màn hình với nhau,giống intent trong Android.

+Có 4 loại Segue là

-Show :Hiển thị view controller mới nhưng sẽ đưa view controller cũ vào stack để có thể điều hướng quay trở lại khi chúng click vào back.

-Present Modally:Hiển thị view controller mới nằm đề lên view controller cũ khi view controller mới đóng thì view controller cũ vẫn được hiển thị trên màn hình.

-Present as Popover:Hiển thị view controller trong popover.

-Custom:Cho phép bạn tự tạo các thao tác chuyển tiếp theo ý mình.

Ví dụ:

-Sử dụng storyboard

giờ các bạn hãy tạo 2 màn hình như sau gồm 2 button :

Giới thiệu Scene và Segue trong Swift

Và các bạn nhớ phải tạo View controler để quản lý từng màn hình.

Để tạo segue các bạn hãy click vào button “Go to scene 2” rồi chuột phải và kéo sang màn hình thứ 2 .

Và đây là kết quả các bạn sau khi tạo

Giới thiệu Scene và Segue trong Swift

Khi tạo thành công nó sẽ có mũi tên liên kết của Segue giữa các màn hình với nhau.

2. Cách truyền dữ liệu sử dụng Segue

Tại màn hình 2 các bạn khai báo biến để bên màn hình gọi truyền dữ liệu vào.

Tại màn hình 1 overite lại phương thức prepare

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
 let data = segue.destination as! ViewController2
 data.strDataFromView1=“Hello"
}

Tại màn hình 2 các bạn chỉ việc set text cho button ,với data đã truyền từ màn hình 1 qua.

class ViewController2: UIViewController {
 var strDataFromView1:String?
@IBOutlet weak var btn_back_to_scene: UIButton!
 override func viewDidLoad() {
super.viewDidLoad()
 btn_back_to_scene.setTitle(strDataFromView1, for: .normal)
}
}

3. Cách quay lại màn hình trước sử dụng Segue

Sử dụng tính năng “unwind” , cho phép cài đặt một phương thức trong ViewController của scene để thực hiện hành động quay lại khi sử dụng segue kết nối các scene với nhau.

Chúng ta khai báo hàm unwind trong View controller 1

@IBAction func unwindTonameMain(_ unwindSegue: UIStoryboardSegue) {
 let sourceViewController = unwindSegue.source
}

Tại màn 2 các bạn chỉ cần kéo view button muốn click quay lại vào nút Exit và chọn “unwindToMain”

Giới thiệu Scene và Segue trong Swift

Bài viết gốc được đăng tải tại codecute.com
  Các cách sử dụng AS, AS?, AS! một cách hiệu quả và an toàn trong code Swift
  Hằng và biến trong Swift
Xem thêm Việc làm it hà nội, đà nẵng, hồ chí minh hấp dẫn trên TopDev

Thủ thuật với Sublime Text (P2)

Thủ thuật với Sublime Text (p2)

Bài viết được sự cho phép của tác giả Tin Tran

Tiếp nối bài viết về thủ thuật lập trình phần trước thì tôi sẽ hướng dẫn thêm cho các bạn về một thủ thuật nho nhỏ của sublime text, thủ thuật này cũng rất là hữu dụng khi các bạn xử lý các dữ liệu của mình. Nào chúng ta cùng bắt đầu tìm hiểu nhé.

  Sublime Text là gì? Hướng dẫn cài đặt Sublime Text 3 chi tiết
  Tổng hợp phím tắt Sublime Text

Vấn đề đặt ra

Giả sử tôi có một danh sách các object như sau, với định dạng là các object kiểu JSON như sau.

[{
   "id": 1,
   "first_name": "Jeanette",
   "last_name": "Penddreth",
   "email": "jpenddreth0@census.gov",
   "gender": "Female",
   "ip_address": "26.58.193.2"
 }, {
   "id": 2,
   "first_name": "Giavani",
   "last_name": "Frediani",
   "email": "gfrediani1@senate.gov",
   "gender": "Male",
   "ip_address": "229.179.4.212"
 }, {
   "id": 3,
   "first_name": "Noell",
   "last_name": "Bea",
   "email": "nbea2@imageshack.us",
   "gender": "Female",
   "ip_address": "180.66.162.255"
 }, {
   "id": 4,
   "first_name": "Willard",
   "last_name": "Valek",
   "email": "wvalek3@vk.com",
   "gender": "Male",
   "ip_address": "67.76.188.26"
 },{
   "id": 1,
   "first_name": "Jeanette",
   "last_name": "Penddreth",
   "email": "jpenddreth0@census.gov",
   "gender": "Female",
   "ip_address": "26.58.193.2"
 }, {
   "id": 2,
   "first_name": "Giavani",
   "last_name": "Frediani",
   "email": "gfrediani1@senate.gov",
   "gender": "Male",
   "ip_address": "229.179.4.212"
 }, {
   "id": 3,
   "first_name": "Noell",
   "last_name": "Bea",
   "email": "nbea2@imageshack.us",
   "gender": "Female",
   "ip_address": "180.66.162.255"
 }, {
   "id": 4,
   "first_name": "Willard",
   "last_name": "Valek",
   "email": "wvalek3@vk.com",
   "gender": "Male",
   "ip_address": "67.76.188.26"
 }{
   "id": 1,
   "first_name": "Jeanette",
   "last_name": "Penddreth",
   "email": "jpenddreth0@census.gov",
   "gender": "Female",
   "ip_address": "26.58.193.2"
 }, {
   "id": 2,
   "first_name": "Giavani",
   "last_name": "Frediani",
   "email": "gfrediani1@senate.gov",
   "gender": "Male",
   "ip_address": "229.179.4.212"
 }, {
   "id": 3,
   "first_name": "Noell",
   "last_name": "Bea",
   "email": "nbea2@imageshack.us",
   "gender": "Female",
   "ip_address": "180.66.162.255"
 }, {
   "id": 4,
   "first_name": "Willard",
   "last_name": "Valek",
   "email": "wvalek3@vk.com",
   "gender": "Male",
   "ip_address": "67.76.188.26"
 }{
   "id": 1,
   "first_name": "Jeanette",
   "last_name": "Penddreth",
   "email": "jpenddreth0@census.gov",
   "gender": "Female",
   "ip_address": "26.58.193.2"
 }, {
   "id": 2,
   "first_name": "Giavani",
   "last_name": "Frediani",
   "email": "gfrediani1@senate.gov",
   "gender": "Male",
   "ip_address": "229.179.4.212"
 }, {
   "id": 3,
   "first_name": "Noell",
   "last_name": "Bea",
   "email": "nbea2@imageshack.us",
   "gender": "Female",
   "ip_address": "180.66.162.255"
 }, {
   "id": 4,
   "first_name": "Willard",
   "last_name": "Valek",
   "email": "wvalek3@vk.com",
   "gender": "Male",
   "ip_address": "67.76.188.26"
 }{
   "id": 1,
   "first_name": "Jeanette",
   "last_name": "Penddreth",
   "email": "jpenddreth0@census.gov",
   "gender": "Female",
   "ip_address": "26.58.193.2"
 }, {
   "id": 2,
   "first_name": "Giavani",
   "last_name": "Frediani",
   "email": "gfrediani1@senate.gov",
   "gender": "Male",
   "ip_address": "229.179.4.212"
 }, {
   "id": 3,
   "first_name": "Noell",
   "last_name": "Bea",
   "email": "nbea2@imageshack.us",
   "gender": "Female",
   "ip_address": "180.66.162.255"
 }, {
   "id": 4,
   "first_name": "Willard",
   "last_name": "Valek",
   "email": "wvalek3@vk.com",
   "gender": "Male",
   "ip_address": "67.76.188.26"
 }]

Giờ tôi muốn lấy ra tất cả các thông tin email ở trong đống JSON này trong vòng một nốt nhạc thì tôi phải làm như thế nào. Các bạn yên tâm vì bây giờ đã có Sublime text để giúp cho các bạn làm việc này một cách nhanh chóng. Cách làm như sau nhé.

1. Bôi đen ký tự [“email”: ]

Thủ thuật với Sublime Text (P2)

2. Nhấn tổ hợp phím Ctrl + F

Thủ thuật với Sublime Text (P2)

3. Nhấn tổ hợp phím ALT + Enter để chọn toàn bộ những ký tự [“email”:]

Thủ thuật với Sublime Text (P2)

4. Nhấn phím > (3 lần) để di chuyển con trỏ sang phải 3 lần.

Thủ thuật với Sublime Text (P2)

5. Nhấn giữ phím Ctrl + Shift và nhấn nút > (Nhấn tới khi nào chọn hết được email thì dừng lại.

Thủ thuật với Sublime Text (P2)

6. Nhấn Ctrl + C để copy email và Ctrl + V để dán kết quả ta được như sau.

Thủ thuật với Sublime Text (P2)

Hy vọng thủ thuật này sẽ giúp ích cho bạn được một phần nào đó để làm việc hiệu quả và đạt hiệu suất cao trong công việc.

Nếu thấy hay thì hãy nhớ like page và share các bài viết giúp tôi nhé.
Cám ơn các bạn đã quan tâm theo dõi.

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

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

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

Những Vuejs concept bắt buộc phải nắm vững – Phần 1

Những Vuejs concept bắt buộc phải nắm vững – Phần 1

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

Khi bắt đầu học / tìm hiểu môn ngôn ngữ hay framework, technology mới thì code được tất nhiên là tốt, nhưng hiểu về concept lại là điều quan trọng nhất, chính vì lí do đó Kieblog giới thiệu thêm bài viết về Vuejs Concept.

Học Vuejs tất nhiên nhanh, nhưng không nên vì quá nhanh mà quên mất những concept quan trọng nhất của Vuejs.

  Call API trong VueJS theo cách thông minh nhất
  Top 3 Vuejs Library không thể không biết

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

1. Computed và methods

Thật ra mục này tương tự như câu hỏi “Computed và Methods khác gì nhau?”.

Đầu tiên, computed tất nhiên không có tham số (đối số) – argument. Thường được sử dụng để xử lý data từ những properties của component hiện tại hoặc chuyển từ component khác tới

Computed properties actually work like getters, they are usually using to compose new data from existing properties and they don’t accept arguments. Computed properties know if the values used in the function changed so they don’t need to run every time to check

Bản chất thì computed gần giống như getters thường sử dụng xử lý dữ liệu từ các props sẵn có, computed không chấp nhận đối số. Computed biết nếu giá trị trong function đã thay đổi thì sẽ thực hiện lại. Vì vậy không cần phải gọi method trong computed nhiều lần để kiểm tra

Còn về methods thì sao. Method là function, cứ nhớ là vậy.

Methods are static functions and they are useful for DOM event handling, logic parts. And you can pass arguments to methods. Methods don’t know if the values used in the function changed so they need to run every time to check.

Method là những function tĩnh, thường được sử dụng để xử lý các sự kiện trên DOM, các tính toán logic. Có thể pass các tham số cho method. Cái bất lợi là method không trigger tham số change khi nào. Bất cứ khi nào muốn update tính toán cho tham số đều phải gọi function.

Hiểu để sử dụng Computed và Methods lúc nào cho đúng cũng là hiểu được Vuejs concept.

2. Lifecycle hooks

Cái thứ hai không thể không nắm rõ là Lifecycle hooks. Đây là nội dung bắt buộc phải nắm rõ vì hiểu được Lifecycle mới biết một component thực sự hoạt động như thế nào?. Trải qua những bước gì để có một component hoàn chỉnh cho ta thấy?

Lifecycle đôi khi cũng được đánh giá là Vuejs concept quan trọng nhất cần phải biết.

Ví dụ như created. Step này component chưa render trên DOM, ta có thể thoải mái chuẩn bị data, gọi API, …

Sau khi đã đầy đủ dữ liệu thì thực hiện tính toán và render trên DOM để có một component hoàn chỉnh.

Kế đến là mounted

Những Vuejs concept bắt buộc phải nắm vững – Phần 1

The mounted hook calls after the template have created and inserted in the DOM, and now you have access to the vm.$el property. But also you should remember that mounted does not guarantee that all child components have also been mounted

Mounted hook thì được gọi sau khi template đã tạo và thêm vào DOM thành công. Lúc này ta có thể truy cập tới thuộc tính vm.$el. Tuy nhiên cần nhớ là mounted không đảm rằng tất cả các component con đã mount ra thành công. Mỗi component có thời gian xử lý và tính toán khác nhau, để phán định các component con thì cần vào mounted trong component con đó.

3. Vue to re-render component như thế nào?

Làm việc với Vuejs tất nhiên không thể tránh khỏi việc rerender lại một component. Dữ liệu update, thao tác người dùng thay đổi, …. Có vô vàn thứ ta cần thực hiện, thông qua rerender component.

Tuy nhiên, render lại component cũng có concept để bám theo. Cách này hay cách kia đều được cân nhắc kĩ lưỡng lợi và hại. Bài viết này sẽ phân tích 2 cách rerender là sử dụng “v-if” với nextTick và “key”.

Cách đầu tiên và thông dụng nhất:

3.1 Sử dụng v-if

<template>
<some-component-re-render v-if="isComponentVisible"/> 
</template>

<script>
export default {
data() {
return {
isComponentVisible: true;
}
},
method() {
forceRerender() {
this.isComponentVisible = false;
this.$nextTick(() => {
this.isComponentVisible = true;
})
} 
} 
} 
</script>

Với cách này, trình tự thực hiện như thế nào?

  • Giá trị của isComponentsVisible khởi tạo là true, vì vậy compoent some-component sẽ được rendered
  • Khi ta gọi hàm forceRerender lại set giá trị cho isComponentsVisible là false
  • Lúc này dừng render component some-component vì kiểm tra thấy v-if bằng false
  • Lúc này next tick set lại isComponentsVisible là true
  • Lúc này giá trị của v-if là true, ta lại render lại compoent some-component thêm một lần nữa.

First, we got to wait until the next tick or we won’t see any changes. In Vue, a tick is a single DOM update cycle. Vue will collect all updates made in the same tick, and at the end of a tick, it will update what is rendered into the DOM based on these updates. If we don’t wait until the next tick, our updates isComponentsVisiblewill just cancel themselves out, and nothing will update.

Đầu tiên ta cần chờ next tick hoặc không thấy cái gì thay đổi. Trong Vue, tick là một DOM cycle độc lập hoàn toàn. Vue sẽ lấy tất cả các nội dung update trong tick, cập nhật và render lại component ở trên DOM. Lúc này ta cần chờ đợi next tick, cập nhật của isComponentsVisiblewill nếu không có gì thay đổi thì component sẽ không được update.

Đó là cách hơi chuối, rối rắm và loằng ngoằng cho mỗi cái mục đích “rerender lại component”. Có cách khác hay hơn để forceRerender một component.

3.2 Sử dụng key

<template>
<component-can-re-render :key="componentKey"/> 
</template>

<script>
export default {
data() {
return {
componentKey: 1;
}
},
method() {
forceRerender() {
return ++this.componentKey;
} 
} 
} 
</script>

Với cách viết này thì mỗi khi function forceRerender() được gọi, giá trị của key componentKey sẽ thay đổi. Vuejs sẽ biết điều này và “xóa component cũ, thực hiện tạo component mới”.

Nên nhớ là re-render không thực hiện trên component cũ. Vuejs thực chất xóa component cũ và tạo lại một cái mới.

Đây cũng là Vuejs concept cần nhớ khi muốn thực hiện rerender lại component.

4. Đừng viết JavaScript expressions khó quá

Khó ở đây không phải viết sao cho tốt, cho dễ refactor. Khó ở đây đang được hiểu là đừng viết những logic quá rắc rối ở template. Hãy thực hiện chúng ở function.

Thử tưởng tượng một component có 30 dòng ở template, nhưng có tới 5 cái v-if, v-for và v-else thì quả thật là tai họa. Đọc để hiểu cũng đã là cả một vấn đề, nói gì tới đọc hiểu rồi còn sửa code. Thảm họa.

Cùng xem xét ví dụ sau:

<template>
<ul>
<li v-for="(car,index) of cars.filter(carItem => carItem.topspeed >= 180 && carItem.color != 'red') :key="index"">
{{ car.model }}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
cars: [
{ model: "BMW", topSpeed: 300, color: "red" }
]
}
}
}
</script>

Chỉ cần khoảng 3,4 điều kiện như thế này lồng nhau. Đọc source thôi cũng nhức cmn cả đầu. Thay vì sử dụng quá nhiều expressions, ta có thể handle ở method. Viết lại như sau sẽ dễ dàng hơn:

<template>
<ul>
<li v-for="(car,index) of sortedCars :key='index'">
{{ car.model }}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
cars: [
{ model: "BMW", topSpeed: 300, color: "red" }
]
}
},
computed: {
sortedCars() {
return this.cars.filter(carItem => carItem.topspeed >= 180 && carItem.color != 'red');
}
}
}
</script>

Cách viết này rõ ràng dễ hiểu hơn nhiều. Dễ theo dõi, template cũng không quá rối mắt.

Nói ít viết Javascript Expression ít đi không hẳn là một Vuejs Concept. Tuy nhiên, đây là điểm đáng để lưu ý khi code với Vue.

5. Tham khảo thêm về Vuejs concept

My pleasure when you are here to read – Have nice weekend – Happy coding!

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

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

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