자신이 작성한 코드 때문에 짜증이 난 적이 있습니까? 고품질 코드를 작성하는 방법에 대해 궁금한 적이 있습니까? 그렇다면 이 주제를 놓치지 마세요! 여기에서 고품질 코드가 무엇인지, 고품질 코드를 작성하는 방법 및 기타 문제에 대해 논의할 수 있습니다. 초보자이든 선임 개발자이든 이 주제에서 공유하고 영감과 지식을 끌어내어 프로그래밍 수준과 작업 효율성을 공동으로 향상시킬 수 있습니다.
I. 소개
품질이 낮은 코드는 최악이고
오류가 발생하기 쉬우며 유지 관리가 어렵습니다.
잦은 버그, 큰 영향,
낮은 효율성, 비표준,
어려운 프로그래밍, 혼란스러운 사고,
높은 품질, 그리고
처음부터 하는 것이 전혀 어렵지 않습니다.
2. 고품질 코드의 특징
다음은 고품질 코드의 몇 가지 특성입니다.
-
강력한 가독성: 고품질 코드는 읽고 이해하기 쉬워야 합니다.명확한 이름 지정, 주석 및 들여쓰기는 물론 구조화된 코드 레이아웃으로 코드를 더 쉽게 이해할 수 있습니다.
-
강력한 유지보수성: 고품질 코드는 수정 및 확장이 쉬워야 합니다.
-
강력한 테스트 가능성: 고품질 코드는 테스트 및 디버그가 쉬워야 합니다. 단위 테스트 및 통합 테스트와 같은 테스트 기술을 사용하면 코드를 더 쉽게 테스트하고 디버그할 수 있습니다.
-
높은 보안: 고품질 코드는 보안이 우수해야 하며 보안 코딩 기술과 보안 테스트 기술을 사용하면 코드를 더욱 안전하고 안정적으로 만들 수 있습니다.
-
우수한 성능: 고품질 코드는 성능이 좋아야 하며 최적화된 알고리즘과 데이터 구조를 사용하면 코드를 보다 효율적으로 만들 수 있습니다.
-
코드 사양: 고품질 코드는 코드 사양을 준수해야 합니다.일관적인 코드 스타일과 표준화된 코딩 습관을 채택하면 코드를 이해하고 유지하기가 더 쉬워집니다.
-
높은 재사용성: 고품질 코드는 재사용성이 좋아야 합니다. 모듈식 설계 및 객체 지향 프로그래밍과 같은 기술을 사용하면 코드를 더 쉽게 재사용할 수 있습니다.
3. 프로그래밍 실습
다음은 Tampermonkey(또는 Greasemonkey) 스크립트를 사용하여 웹 페이지에서 PDF 파일을 자동으로 다운로드하는 코드입니다. 특히 이 스크립트는 https://copyright.lib.* .. **/pdfindex.jsp 페이지를 수신합니다.
코드의 주석은 스크립트의 각 부분의 기능과 기능을 매우 자세하게 설명했습니다. 간략한 소개는 다음과 같습니다.
- 스크립트는 먼저 최종 보고서 창의 DOM 요소를 얻기 위해 페이지가 완전히 로드될 때까지 기다립니다.
- 스크립트는 PDF 다운로드를 시작하는 최종 보고서 창 아래에 버튼을 삽입합니다.
- 사용자가 다운로드 버튼을 클릭하면 스크립트가 자동으로 모든 PDF 페이지를 통과하여 단일 PDF 파일로 변환합니다.
- PDF의 각 페이지는 이미지 형태로 저장되며 스크립트는 먼저 이미지 링크를 얻은 다음 jQuery의 $.get() 메서드를 사용하여 이미지 데이터를 얻습니다. 이 데이터는 서버 측에서 base64 인코딩으로 압축되어 JSON 형식으로 클라이언트에 반환됩니다.
- 그런 다음 스크립트는 이미지 데이터를 Blob 형식으로 변환하고 새 이미지 개체를 사용하여 페이지에 로드합니다. 이 단계는 jsPDF.addImage() 메서드가 이미지 URL에서 이미지 데이터를 가져와야 하기 때문에 한 번만 호출되도록 합니다.
- 그런 다음 스크립트는 이미지 개체를 jsPDF에 추가하여 모든 페이지가 추가되면 하나의 PDF 파일로 저장되도록 합니다.
전반적으로 이 스크립트는 비동기 함수, Promise, MutationObserver, jQuery 및 jsPDF를 비롯한 다양한 기술과 도구를 사용합니다. 이것은 여러 페이지와 이미지 다운로드를 처리할 때 스크립트를 매우 효율적이고 안정적으로 만듭니다.
넷째, 실제 코드
// ==UserScript==
// @name pdf_downloader
// @namespace https://blog.rhilip.info/
// @version 1.0
// @description 下载pdf
// @author DR-ZF-
// @match https://copyright.lib.****.***.**/pdfindex.jsp*
// @require https://unpkg.com/[email protected]/dist/jspdf.umd.min.js
// @require https://unpkg.com/[email protected]/dist/jquery.js
// ==/UserScript==
/* globals $, jspdf */
// 参考油猴NSFC_conclusion_downloader by Rhilip,进行改写
// Copy and edit from https://stackoverflow.com/a/61511955
function waitForElm(selector) {
return new Promise(resolve => {
if ($(selector).length > 0) {
return resolve($(selector));
}
const observer = new MutationObserver(mutations => {
if ($(selector).length > 0) {
resolve($(selector));
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
(async function() {
'use strict';
// 等待页面加载
const conclusionReportTab = await waitForElm('#tool_Zoom');
// 准备交互按钮,并插入到页面中
const downloadBtn = $('<button type="button" class="el-button el-button--default el-button--medium is-round">下载全文</button>');
conclusionReportTab.after(downloadBtn);
// 点击交互按钮时需要开始下载操作
downloadBtn.click(async () => {
downloadBtn.prop('disabled', true).addClass('is-disabled');
if (!/无页面/.test(conclusionReportTab.text())) {
// 获得项目信息
const urlParams = new URLSearchParams(location.search);
const dependUintID = urlParams.get('fid');
// 准备需要的PDF文件,并删除初始页
const doc = new jspdf.jsPDF();
doc.deletePage(1);
doc.setDocumentProperties({
title: 'pdf_downloader',
subject: location.href,
creator: 'pdf_downloader'
});
// 核心下载方法
const image = new Image();
for (let i=1;;i++) {
downloadBtn.text(`正在下载第 ${
i} 页`);
// 获得图片链接
const response = await $.get('/jumpServlet?', {
page: i, fid: dependUintID });
console.log(response);
if (!response){
break; // 此处应该明确为false才break
}
const jsonResponse = JSON.parse(response);
const {
list } = jsonResponse;
let firstSrc, firstId
if (Array.isArray(list) && list.length > 0) {
const [firstItem] = list;
if (firstItem.src && firstItem.id) {
firstSrc = firstItem.src;
firstId = firstItem.id;
} else {
console.error(`Unexpected response data. Missing 'src' or 'id' property. Response: ${
JSON.stringify(response)}`);
}
} else {
console.error(`Unexpected response data. 'list' property not found or empty array. Response: ${
JSON.stringify(response)}`);
}
// 获得Blob形式的imageData,这样可以防止image.src和jsPDF.addImage会产生两次图片请求,浪费带宽
// (实际变成了一次请求服务器和两次请求本地blob)
try {
const imageDataAsBlob = await $.ajax({
url: firstSrc,
method: 'GET',
xhrFields: {
responseType: 'blob'}
});
// 加载图片并获得图片的 width, height 属性
image.src = URL.createObjectURL(imageDataAsBlob);
await image.decode();
// 将图片添加进PDF中
doc.addPage([image.width, image.height], image.width < image.height ? 'p' : 'l');
doc.addImage(image, "PNG", 0, 0, image.width, image.height);
} catch (e) {
break; // 如果中间有任何失败,则直接break
}
}
// 我们并没法 await 保存过程,所以直接显示下载完成就好,浏览器处理好会自动显示下载文件
doc.save(`PDF下载.pdf`);
downloadBtn.text('下载完成');
}
});
})();
V. 요약
이 코드의 주요 기능은 웹 페이지에서 PDF 파일을 다운로드하는 것입니다. 좋은 점은 다음과 같습니다.
-
비동기 함수 및 약속이 사용됩니다. 코드는
async
함수Promise
와 개체를 사용하므로 페이지 로드 및 이미지 다운로드와 같은 시간 소모적인 작업을 기다리는 동안 코드가 계속해서 다른 작업을 수행할 수 있으므로 페이지 차단 또는 정지를 방지할 수 있습니다. -
MutationObserver 사용: MutationObserver를 사용하여 DOM 트리 변경 사항을 모니터링한 다음 대상 요소가 나타날 때 후속 코드를 실행하면 페이지 로딩 속도와 성능을 개선하고 느린 페이지 로딩으로 인한 코드 실행 오류를 피할 수 있습니다.
-
높은 코드 가독성: 변수 및 함수 이름은 의미가 있고 주석은 명확하고 명확하며 코드 구조는 명확하고 간결하며 이해하고 유지하기 쉽습니다.
-
jQuery 및 jspdf 라이브러리 사용: 이 코드는 jQuery 라이브러리를 사용하여 DOM 조작을 단순화하고 jspdf 라이브러리를 사용하여 PDF 파일을 쉽게 생성합니다.
-
적절한 오류 처리: 코드는 HTTP 요청 및 기타 비정상적인 상황을 올바르게 처리하고 동시에 예외가 발생하면 프로그램을 종료하고 해당 오류 프롬프트를 제공하여 코드에서 심각한 실행 오류를 방지합니다.