Sử dụng công cụ AI (Github Copilot) trong việc hỗ trợ phát triển (dev/code)

Ngày nay có rất nhiều công cụ hỗ trợ cho việc phát triển code dựa trên AI như:
- ChatGPT
- Clause
- Gemini
- GitHub Copilot
- Replit v.v…

Chúng là những công cụ hỗ trợ lý tưởng cho việc lập trình. Có rất nhiều cách tiếp cận trong việc sử dụng AI vào trong code, như việc sử dụng AI cho việc tự động hóa viết code thông qua cấu hình MCP
, hay như việc sử dụng AI như một trợ lý
ảo cho lập trình.
Trong bài viết này tập trung vào việc trình bày sử dụng AI như một trợ lý
ảo cho lập trình viên (Github Copilot) mà tác giả đã sử dụng trong dự án thực tế.
Toàn bộ code minh họa trong bài viết Chia tầng (layered) cho ứng dụng
Spring Boot
được tạo từ Github Copilot thông qua các câu Prompt được giới thiệu trong bài viết này.
Một số lưu ý trước khi bắt đầu:
Nếu chỉ để tạo CRUD đơn thuẩn cho một đối tượng cụ thể với những công cụ AI mạnh mẽ như ngày nay có thể dùng 1 câu lệnh để tạo ra được một implement hoàn chỉnh, hoặc sử dụng các công cụ generate code như
JHipster
. Mình chia nhỏ thành các câu lệnh nhỏ để minh họa cho việc AI cần những thông tin đầu vào là gì để hoạt động tốt.
Các câu trả lời của AI có thể sẽ không hoàn toàn chính xác, mình hay gặp trong trường hợp như
import
có khi AI đưa ra một thư viện khoặc một hàm không có trong thực tế. AI rất mạnh mẽ khi xử lý các phần liên quan đến thuật toán và logic.
Một số lệnh build-in hữu ích
Trong Github Copilot (sau đây gọi tắt là Copilot hoặc AI) có xây dựng sẵn một số câu lệnh cho việc sử dụng

/explain
ta bôi đen vào đoạn code để cho AI diễn giải logic, rất hữu ích khi tìm hiểu code của một dự án khác, hoặc muốn biết tính năng để bổ xung hoặc thay đổi chức năng cũ/fix
khi class của chúng ta bị lỗi complie (lỗi đỏ) chọn lệnh này AI sẽ tìm hiểu dựa trên ngữ cảnh (là file hiện tại, và các thông tin hỏi trước đó) để đưa ra giải pháp xử lý tình huống/tests
lệnh này rất hữu ích khi giúp chúng ta viết các UnitTest cho một class cụ thể, đứng tại class muốn viết UnitTest ta chỉ cần gọi lệnh này. Cần lưu ý, có những mô hình AI đưa ra những câu trả lời tối thiểu (bỏ qua phần import, tên cho test case, comment) ta có thể bổ xung sau câu lệnh /tests with full import and description for each test case/simplify
thường mình sẽ chạy câu lệnh này cuối cùng khi đã test nghiệp vụ chạy đúng, đứng tại một file gọi lệnh này AI sẽ tính toán và đưa ra một phương án code tối ưu gọn gàng hơn. Wow nhiều trường hợp mình cũng không ngờ tới có thể tối ưu thêm được./doc
dùng để tạo JavaDoc hoặc tạo OpenAPI/Swagger cho APIs rất hiệu quả
Các câu lệnh build-in khác các bạn có thể tìm hiểu và sử dụng
Xây dựng các câu lệnh (prompt) cho AI hỗ trợ viết code
Dưới đây là các quan điểm và ý kiến cá nhân của mình, nó có thể không hoàn toàn đúng, mình chỉ đúc rút lại trong quá trình sử dụng AI trong các dự án thực tế.
Từ khóa quan trọng hơn ngữ pháp
Các mô hình học máy với ngôn ngữ lớn LLM đào tạo dữ liệu và đánh dấu, lưu trữ dữ liệu giá trị, để truy xuất dữ liệu đã được xử lý AI sử dụng các từ khóa ‘tokens’ và các cửa sổ ngữ cảnh ‘context window’ để đưa ra câu trả lời, AI không suy luận ra câu trả lời mà đưa ra các khả năng của câu trả lời dựa trên dữ liệu đã có.
Với một đoạn mệnh lệnh prompt
mà chúng ta đưa vào AI sẽ tìm kiếm các từ khóa quan trọng, kết hợp với ngữ cảnh trước đó để lục tìm các câu trả lời cho chúng ta. Ví dụ khi mình muốn AI tạo giúp một class để cho thực thể Product câu prompt mình dùng là
create ProductEntity use Record in Java to store ProductRequest, also add more those fields: status, createdDate, modifiedDate, userId
Một số từ khóa mà AI sẽ dựa vào đó để tìm câu trả lời (theo mình): create
, record
, more those fields
…
Kết quả đầu ra đúng như mình mong muốn, AI sẽ tham khảo ngữ cảnh trước đó là ProductRequest
gồm những trường nào, nó sẽ thêm những trường mà trong câu prompt mình gợi ý, AI sẽ cho mình kiểu record
không phải là class hoặc interface, các kiểu dữ liệu mình không đưa cụ thể nhưng với tên của biến AI có thể suy luận ra được kiểu dữ liệu mà các biến khác với tên này hay dùng, nó sẽ gợi ý cho chúng ra các kiểu dữ liệu đó.
package com.koder.course.applayered.entity;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* Entity record for Product, storing all request fields plus status, timestamps, and userId.
*/
public record ProductEntity(
UUID uuid,
String name,
String sku,
BigDecimal price,
String desc,
String status,
LocalDateTime createdDate,
LocalDateTime modifiedDate,
UUID userId
) {}
câu lệnh trên nếu viết đầy đủ mặt ngữ pháp (có thể không chuẩn xác) sẽ có dạng
I want to create a class with the name is ProductEntity, it has record type and has all fields of ProductRequest, also....
Chúng ta có thể nhận được kết quả tương tự, một số từ khóa sẽ không nằm trong ngữ pháp của câu prompt.
Mình muốn nhấn mạnh ở đây là ta có thể viết những prompt cho AI ở mức độ ngữ pháp tối thiểu (đôi khi có thể sai), do vậy những lập trình viên đang kém chút về ngữ pháp cũng có thể sử dụng.
Oh, vậy có thể sử dụng tiếng Việt được không? Được, nhưng mình nghĩ, việc training và đánh dấu dữ liệu của AI hiện tiếng Anh đang chiếm số lượng lớn trong lĩnh vực phần mềm, nếu ta đưa prompt bằng tiếng Việt sẽ cần qua bộ thông dịch, do vậy các từ khóa quan trọng mà ta muốn có trong prompt có thể sẽ không được dữ nguyên khi prompt -> dịch TA -> tạo token -> tìm kiếm, do vậy kết quả có thể không được như ta mong muốn. AI thì luôn đưa ra câu trả lời với bất kỳ dữ liệu đầu vào nào.
AI là chương trình điện toán, nên không có cảm xúc, do vậy cũng không cần thêm vào các các câu chào hỏi và cảm ơn, đôi khi thêm vào các câu như vậy làm AI thêm những tính toán không cần thiết.
Một prompt có giới hạn ký tự
Một lệnh đưa cho AI, nó sẽ phân tích câu lệnh đầu vào và biến thành tokens, mỗi AI có giới hạn tokens, con số chính sác mình không nhớ rõ. Nhưng nó cũng khuyển khích một điều, đưa càng nhiều dữ liệu, đầu vào càng tốt.
Trong dự án cũ cần maintain khi AI không theo mình phát triển từ đầu, hoặc ngôn ngữ cách viết trong dự án đó khá cũ và có nhiều khác biệt so với mô hình code ngày nay, cách tốt nhấy là cung cấp nhiều thông tin nhất có thể cho AI. Có một case cụ thể trong dự án như sau, dự án A phát triển trên một ngôn ngữ mới mà mình chưa làm trước đó, mình cần xử lý một nghiệp vụ merge hai file svc lại với nhau và có một số nghiệp vụ cần thực hiện khi merge. Để thực hiện việc này mình sẽ xây dựng câu prompt có cấu trúc như sau:
- Ngôn ngữ mong muốn
- Cung cấp cấu trúc của 2 file csv
- Mô tả nghiệp vụ
- Mô tả một sổ tình huống với dữ liệu cụ thể
AI đưa ra được phiên bản đầu tiên
- Yêu cầu test đầu vào với dữ liệu giả định
- Mô tả thêm những case đặt biệt
- Check null, empty, …
AI cập nhật và đưa ra phiên bản tiếp theo, cứ lặp lại như vậy đến khi cảm thấy được phiên bản tốt hoặc có thể chấp nhận được.
Nó có giới hạn nhưng cứ cung cấp càng nhiều càng tốt
Ngoài cửa sổ chat, có thể hỏi ngay trên Editor
Khi ta sử dụng Copilot với các IDE hỗ trợ như IntelliJ hoặc Visual Studio Code việc gợi ý code được thực hiện ngay trên Editor, AI đưa ra các đoạn code tiếp theo dựa trên ngữ cảnh đang có được.
Để cụ thể hóa gợi ý, code ta có thể tạo ra các code comment, dựa vào comment code AI sẽ đưa ra gợi ý (code suggestion) cho chức năng mong muốn, thông thường sẽ dùng phím Tab để chấp nhận hoặc dấu cách để bỏ qua

Với code comment là
// Validates if a product with the given name already exists.
// If it does, it throws the ProductNameExistingException exception
AI sẽ gợi ý cho ta một hàm tương ứng, ở đây ta có thấy đoạn code được gợi ý, hàm này bản chất không tồn tại AI dựa trên dữ liệu thông thường hàm sẽ có tên như vậy khi sử dụng JPA, nhưng ở đây mình đã tạo ra hàm khác có tên là existsByNameIgnoreCase
, do vậy sẽ bị báo đỏ khi apply đoạn code này. Ta chỉ điều chình để phù hợp với tên hàm thực tế là được
boolean exists = productEntityRepository.existsByName(productName);
Danh sách các câu lệnh prompt
để xây dựng CRUD APIs trên Spring Boot
Tham khảo lại bài viết về chia lớp cho ứng dụng CRUD tại đây
Trước hết ta hình dung luồng để xây dựng ứng dụng: DTO -> Interface for APIs -> Entity -> Repository -> Exceptions -> Validator -> Advice Controller -> Mapper -> Service -> Implement APIs -> support to create SQL file
Code được tạo ra cần được tinh chỉnh bởi developer, nhưng khi đã hiểu về Code và được API hỗ trợ việc tạo code việc lập trình trở lên dễ dàng hơn, và code có chất lượng tốt hơn.
Tạo các DTO
#1 create ProductRequest with those fields: uuid, name, sku, price, base, desc
#2 can you use lombok
#3 use valid for all field in ProductRequest
Đây là kết quả ta nhận được
package com.koder.course.applayered.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import java.math.BigDecimal;
import java.util.UUID;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ProductRequest {
@NotNull
private UUID uuid;
@NotBlank
private String name;
@NotBlank
private String sku;
@NotNull
@Positive
private BigDecimal price;
@NotBlank
private String base;
@NotBlank
private String desc;
}
Tạo ProductResponse
create ProductResponse with all fields same ProductRequest but add more those fields: status, createDate, updateDate
Tạo interface cho CURD APIs
create interface for CRUD restful apis for Product, using ProductRequest as request object, productresponse as response object
Khi ta muốn tạo tài liệu cho API, ta có thể dùng lệnh
/doc add swagger (openAPI) for this CRUD, use ProblemDetail for case error
Nó sẽ bổ xung thêm annation cho các interface đã được tạo ra trước đó
@Operation(summary = "Create a new product")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Product created",
content = @Content(schema = @Schema(implementation = ProductResponse.class))),
@ApiResponse(responseCode = "400", description = "Invalid input",
content = @Content(schema = @Schema(implementation = ProblemDetail.class)))
})
@PostMapping
ResponseEntity<ProductResponse> createProduct(
@RequestBody ProductRequest request
);
Trong trường hợp mình quên không thêm dependency cho OpenAPI, ta có thể nhờ AI add
help me add openapi dependency
và đây là kết quả
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
Tạo Entity Object và Repository Interface
#1 create ProductEntity use Record in Java to store ProductRequest, also add more those field: status, createdDate, modifiedDate, userId
#2 create a repository for ProductEntity use CRUD jpa
Tạo exception class
create ProductNameExistingException extend RuntimeException
Tạo validator
Với logic cho validator như mình đã miêu tả ở trên, sau khi tạo ra một class trống, đưa ra một số mô tả về class nó sẽ gợi ý cho ta method mong muốn
// Validates if a product with the given name already exists.
// If it does, it throws the ProductNameExistingException exception
Tạo lớp mapper
create ProductMapper class, it has a method for mapping ProductEntity to ProductResponse, becareful ProductEntity with type record
Tạo ProductService
ProductService kết hợp sử dụng mapper
, repository
do vậy ta tạo mẫu một class và mô tả method mong muốn, AI có thể bị nhầm khi gợi ý bởi các dự án trước đó đã thực hiện. Như hiện tại trên máy mình cần khai báo tường minh cho AI không sử dụng reactive, vì các dự trước đó mình có sử dụng reactive do vậy nó có thể gợi ý sử dụng reactive.
// Method to save a product from ProductRequest
// no reactive implementation here, just a simple save
// return ProductResponse
public ProductResponse saveProduct(ProductRequest productRequest, String userId) {
log.info("Saving product: {}", productRequest);
ProductEntity productEntity = productMapper.toProductEntity(productRequest, userId);
ProductEntity savedProduct = productRepository.save(productEntity);
log.info("Product saved successfully: {}", savedProduct);
return productMapper.toProductResponse(savedProduct);
}
Lần đầu có thể bị sai cần điều chỉnh, nhưng những lần sau khi AI quen
với style viết code như vậy nó sẽ gợi ý sát hơn.
Tương tự với ProductApisImpl
Tạo GlobalExceptionHandler
Help me create advice controller class to catch exception then then response to client
AI gợi ý cho ta tạo một ErrorResponse
class và GlobalExceptionHandler
nhưng trong GlobalExceptionHandler thiếu việc handle cho case trùng tên ProductNameExistingException
ta có thể yêu cầu thêm
add execption for ProductNameExistingException return badrequest code 400
Tổng kết
- Có nhiều cách áp dụng AI để hỗ trợ việc lập trình ta lựa chọn và áp dụng linh hoạt
- Sử dụng hiệu quả các build-in command của AI
- AI cũng có thể sai
- AI không suy luận như con người, AI đưa ra câu trả lời dựa trên các tập dữ liệu đã có được, dựa vào tokens phân tích từ prompt truyền vào các các cửa sổ ngữ cảnh AI đưa ra các câu trả lời tương ứng
- Hiểu được nguyên tắc AI để xây dựng các prompt hiệu quả hơn
Để lại một bình luận