>  기사  >  웹 프론트엔드  >  나만의 JavaScript 코드베이스 설계 및 구축: 팁과 요령

나만의 JavaScript 코드베이스 설계 및 구축: 팁과 요령

黄舟
黄舟원래의
2017-02-22 13:48:531324검색

코드베이스: 우리는 항상 이를 사용합니다. 코드 라이브러리는 개발자가 프로젝트에서 사용할 코드를 패키징하는 곳으로, 항상 시간을 절약하고 바퀴를 재발명하는 것을 방지합니다. 오픈 소스든 비공개 소스든 재사용 가능한 패키지를 갖는 것이 동일한 기능을 사용하여 패키지를 계속해서 구축하거나 과거 프로젝트에서 수동으로 복사하여 붙여넣는 것보다 낫습니다.

작가의 추가 기사

  • Stop Maiming Bodies: The Perils of Pixel Font-Size

  • ES2016: JavaScript의 미래는 개발자 중심이어야 할까요?

패키징된 코드 외에 코드 베이스를 더 정확하게 설명할 수 있나요? 몇 가지 예외를 제외하고 코드베이스는 일반적으로 하나의 파일이거나 동일한 폴더에 있는 여러 파일입니다. 해당 코드는 별도로 저장하여 프로젝트에서 정상적으로 사용할 수 있어야 합니다. 라이브러리를 사용하면 프로젝트에 따라 구조나 동작을 조정할 수 있습니다. USB 인터페이스를 통해서만 통신하는 USB 장치를 상상해 보십시오. 마우스, 키보드 등 일부 장치는 해당 장치에서 제공하는 인터페이스를 통해 구성할 수 있습니다.

이 글에서는 라이브러리 파일을 빌드하는 방법에 대해 설명하겠습니다. 대부분의 방법은 다른 언어에도 적용할 수 있지만 이 문서에서는 JavaScript 라이브러리 구축에 중점을 둡니다.

자체 Javascript 라이브러리를 구축하는 이유는 무엇입니까?

무엇보다도 라이브러리 파일을 사용하면 기존 코드를 쉽게 재사용할 수 있습니다. 파일을 복사하기 위해 이전 프로젝트를 파낼 필요가 없으며 라이브러리 파일을 가져오기만 하면 됩니다. 또한 이를 통해 애플리케이션을 구성 요소화하여 애플리케이션의 코드 기반을 더 작고 유지 관리하기 쉽게 만들 수 있습니다.

设计和构建你自己的JavaScript代码库:提示与技巧

Christ Church Library(출처)

특정 기능을 더 쉽게 구현하거나 재사용할 수 있는 추상 코드는 라이브러리에 패키징할 수 있습니다. 파일. jQuery는 흥미로운 예입니다. jQuery의 API에는 단순화된 DOM API가 많이 있지만, 크로스 브라우저 DOM 작업이 어려웠던 과거에는 상당한 의미가 있었습니다.

오픈소스 프로젝트가 인기를 얻고 이를 사용하는 개발자가 많아지면 사람들이 질문을 하거나 코드를 제공하여 개발에 참여할 가능성이 높습니다. 어느 쪽이든, 이는 라이브러리와 이에 의존하는 프로젝트에 도움이 됩니다.

인기 있는 오픈 소스 라이브러리도 좋은 기회를 가져올 것입니다. 회사는 귀하의 작업 품질을 인식하고 귀하에게 제안을 할 수 있습니다. 어쩌면 회사에서 귀하의 프로젝트를 애플리케이션에 통합하도록 요청할 수도 있습니다. 결국, 당신보다 당신의 프로젝트를 더 잘 아는 사람은 없습니다.

물론 습관일 수도 있습니다. 타이핑을 즐기고, 다른 사람을 돕고, 그 과정에서 배우고 성장하는 것을 즐기세요. 한계를 뛰어넘고 새로운 것을 시도할 수 있습니다.

범위 및 대상

첫 번째 코드 줄을 작성하기 전에 라이브러리의 기능을 결정해야 합니다. 즉, 대상을 설정해야 합니다. 이 목표를 통해 이 라이브러리로 해결하려는 문제에 집중할 수 있습니다. 문제를 해결할 때 코드 베이스의 원래 형식을 사용하고 기억하기가 더 쉽다는 점을 명심하세요. API가 단순할수록 사용자가 코드 베이스를 배우기가 더 쉽습니다. Unix 디자인 철학 소개:

한 가지 일을 잘 수행하세요.

스스로에게 물어보세요. 코드 기반이 해결하는 문제는 무엇인가요? 어떻게 해결하실 건가요? 혼자서 모든 작업을 수행하시겠습니까, 아니면 다른 사람의 코드 기반을 가져오시겠습니까?

코드베이스가 아무리 크더라도 로드맵을 만들어 보세요. 원하는 모든 기능의 목록을 만들고 최소한의 실행 가능한 제품과 같은 작지만 문제 해결 코드 기반이 될 때까지 가능한 한 많은 조각으로 나눕니다. 이것이 첫 번째 버전이 됩니다. 여기에서 각각의 새로운 기능에 대한 마일스톤을 설정할 수 있습니다. 기본적으로 프로젝트를 비트 수준의 코드 덩어리로 전환하여 각 기능이 더 훌륭하고 흥미롭게 작동하도록 만듭니다. 저를 믿으십시오. 이것이 당신의 몸매를 좋게 유지해 줄 것입니다.

API 디자인

저는 사용자 관점에서 코드 베이스를 개발하고 싶다고 생각합니다. 사용자 중심 디자인이라고 할 수 있습니다. 본질적으로 코드베이스의 개요를 작성하여 더 많은 생각을 하게 하고 이를 선택하는 사람들이 더 쉽게 사용할 수 있도록 합니다. 동시에 이 문서의 뒷부분에서 설명할 사용자 정의가 필요한 부분에 대해 생각해야 합니다.

궁극의 API 테스트는 자신만의 기술을 시험해보고 프로젝트에서 코드 기반을 사용하는 것입니다. 이전 코드를 귀하의 코드로 바꾸고 원하는 기능을 충족하는지 확인하십시오. 코드 기반을 가능한 한 직관적으로 만들어 경계 조건에서 보다 유연하게 사용하고 사용자 정의할 수 있도록 하십시오(자세한 내용은 이후 기사에서 설명).

사용자 에이전트 문자열에 대한 코드 베이스의 개요는 다음과 같습니다.

// Start with empty UserAgent string var userAgent = new UserAgent; 
// Create and add first product: EvilCorpBrowser/1.2 (X11; Linux; en-us) var application = new UserAgent.Product('EvilCorpBrowser', '1.2');
application.setComment('X11', 'Linux', 'en-us');
userAgent.addProduct(application); // Create and add second product: Blink/20420101 var engine = new UserAgent.Product('Blink', '20420101');
userAgent.addProduct(engine); // EvilCorpBrowser/1.2 (X11; Linux; en-us) Blink/20420101 userAgent.toString(); 
// Make some more changes to engine product engine.setComment('Hello World'); // EvilCorpBrowser/1.2 (X11; Linux; en-us) Blink/20420101 (Hello World) userAgent.toString();

코드의 복잡성에 따라 정리하는 데 시간이 걸릴 수 있습니다. 디자인 패턴을 활용하는 것은 코드 기반을 구성하는 좋은 방법이며 일부 기술적인 문제를 해결할 수도 있습니다. 이는 또한 새로운 기능을 추가하기 위한 광범위한 리팩토링을 방지합니다.

유연성과 사용자 정의

유연성은 코드베이스를 강력하게 만드는 요소이지만 사용자 정의할 수 있는 것과 불가능한 것의 경계를 결정하는 것은 어렵습니다. Chart.js와 D3.js가 좋은 예입니다. 두 코드 라이브러리 모두 데이터 시각화에 사용됩니다. Chart.js를 사용하면 다양한 형식의 내장 차트를 쉽게 만들 수 있습니다. 그러나 이미지에 대한 더 많은 제어를 원한다면 D3.js가 필요합니다.

사용자에게 제어권을 부여하는 방법에는 구성, 공개 메소드 노출, 콜백 및 이벤트 등 여러 가지가 있습니다.

코드 베이스 구성은 일반적으로 초기화 전에 수행됩니다. 그러나 일부 코드 라이브러리를 사용하면 런타임에 구성을 수정할 수 있습니다. 구성은 일반적으로 작은 부품으로 제한되며 나중에 사용하기 위해 값을 수정하는 것만 허용됩니다.

// Configure at initialization var userAgent = new UserAgent({
  commentSeparator: ';' }); // Run-time configuration using a public method userAgent.setOption('commentSeparator', '-'); 
  // Run-time configuration using a public property userAgent.commentSeparator = '-';

方法通常是暴露给实例使用的,比如说从实例中获取数据,或者设置实例的数据和执行操作。

var userAgent = new UserAgent; // A getter to retrieve comments from all products userAgent.getComments(); 
// An action to shuffle the order of all products userAgent.shuffleProducts();

回调通常是在公共的方法中被传递的,通常在异步操作后执行用户的代码。

var userAgent = new UserAgent;

userAgent.doAsyncThing(function asyncThingDone() { // Run code after async thing is done });

事件有很多种可能。有点像回调,除了增加事件句柄是不应该触发操作的。事件通常用于监听,你可能会猜到,这可是事件!更像回调的是,你可以提供更多的信息和返回一个数值给代码库去进行操作。

var userAgent = new UserAgent; // Validate a product on addition userAgent.on('product.add', function onProductAdd(e, product) { 
var shouldAddProduct = product.toString().length < 5; // Tell the library to add the product or not return shouldAddProduct;
});

在一些例子中,你可能允许用户对你的代码库进行扩展。因此,你需要暴露一些公共方法或者属性来让用户填充,像Angular的模块 (angular.module('myModule'))和Jquery的 fn(jQuery.fn.myPlugin)或者什么都不做,只是简单的让用户获取你的代码库的命名空间:

// AngryUserAgent module // Has access to UserAgent namespace (function AngryUserAgent(UserAgent) { 
// Create new method .toAngryString() UserAgent.prototype.toAngryString = function() { return this.toString().toUpperCase();
  };

})(UserAgent); // Application code var userAgent = new UserAgent; // ... // EVILCORPBROWSER/1.2 (X11; LINUX; EN-US) BLINK/20420101 userAgent.toAngryString();

类似的,这允许你重写方法。

// AngryUserAgent module (function AngryUserAgent(UserAgent) { // Store old .toString() method for later use var _toString = UserAgent.prototype.toString; 
// Overwrite .toString() UserAgent.prototype.toString = function() { return _toString.call(this).toUpperCase();

  };

})(UserAgent); var userAgent = new UserAgent; // ... // EVILCORPBROWSER/1.2 (X11; LINUX; EN-US) BLINK/20420101 userAgent.toString();

在后面的例子中,允许你的用户获取代码库的命名空间,让你在对扩展和插件的定义方面上的控制变小了。为了让插件遵循一些约定,你可以(或者是应该)写下文档。

测试

对测试驱动开发(test-driven development)来 说,写下大纲是良好的开始。简单来说,指的是在你写实际的代码库之前,在你写下测试准则的时候。如果测试检查的是你的代码特性是否跟期待的一样,以及你在 写代码库之前写测试,这就是行为驱动开发。不管怎样,如果你的测试覆盖了你的代码库的每一个特性,而且你的代码通过了所有的测试。你可以确定你的代码是可 以正常工作的。

Jani Hartikainen讲述了如何利用Mocha来进行单元测试 Unit Test Your JavaScript Using Mocha and Chai。在使用Jsmine,Travis,Karma测试JavaScript (Testing JavaScript with Jasmine, Travis, and Karma)这篇文章中,Tim Evko展示了怎么通过另一个叫做Jasmine的框架来设置良好的测试流程。这两个测试框架都是非常流行的,但还有适应别的需求的其他框架。

我在这篇文章前面撰写的大纲,已经讲述了它期待怎样的输出。这是一切测试的开始:从期望出发。关于我的代码库的一个Jasmine测试像是这样:

describe(&#39;Basic usage&#39;, function () {
  it(&#39;should generate a single product&#39;, function () { // Create a single product var product = new UserAgent.Product(&#39;EvilCorpBrowser&#39;, &#39;1.2&#39;);
    product.setComment(&#39;X11&#39;, &#39;Linux&#39;, &#39;en-us&#39;);

    expect(product.toString())
      .toBe(&#39;EvilCorpBrowser/1.2 (X11; Linux; en-us)&#39;);
  });

  it(&#39;should combine several products&#39;, function () { var userAgent = new UserAgent; 
  // Create and add first product var application = new UserAgent.Product(&#39;EvilCorpBrowser&#39;, &#39;1.2&#39;);
    application.setComment(&#39;X11&#39;, &#39;Linux&#39;, &#39;en-us&#39;);
    userAgent.addProduct(application); // Create and add second product var engine = new UserAgent.Product(&#39;Blink&#39;, &#39;20420101&#39;);
    userAgent.addProduct(engine);

    expect(userAgent.toString())
      .toBe(&#39;EvilCorpBrowser/1.2 (X11; Linux; en-us) Blink/20420101&#39;);
  });

  it(&#39;should update products correctly&#39;, function () { var userAgent = new UserAgent; 
  // Create and add first product var application = new UserAgent.Product(&#39;EvilCorpBrowser&#39;, &#39;1.2&#39;);
    application.setComment(&#39;X11&#39;, &#39;Linux&#39;, &#39;en-us&#39;);
    userAgent.addProduct(application); // Update first product application.setComment(&#39;X11&#39;, &#39;Linux&#39;, &#39;nl-nl&#39;);

    expect(userAgent.toString())
      .toBe(&#39;EvilCorpBrowser/1.2 (X11; Linux; nl-nl)&#39;);
  });
});

一旦你对你的API设计的第一个版本完全满意,是时候开始思考结构和你的代码库应该如何被使用。

模块加载器兼容性

你或许使用过模块加载器。使用你的代码库的开发者有可能使用加载器,所以你会希望自己的代码库与模块加载器是兼容的。但兼容哪一个呢?应该怎么从CommonJS,RequireJS,AMD和其他加载器中挑选呢?

사실 굳이 고를 필요는 없어요! UMD(Universal Module Definition)는 여러 로더를 지원하는 것이 목표인 규칙입니다. 온라인에서 다양한 스타일의 스니펫을 찾거나 UMD GitHub 저장소에서 학습하여 코드베이스와 호환되게 만들 수 있습니다. 이러한 템플릿 중 하나로 시작하거나 선호하는 빌드 도구로 UMD를 추가하면 더 이상 모듈 로더에 대해 걱정할 필요가 없습니다.

ES2015의 가져오기/내보내기 구문을 사용하려면 Babel 및 Babel의 UMD 플러그인을 사용하여 코드를 ES5로 변환하는 것이 좋습니다. 이렇게 하면 호환되는 코드 베이스를 생성하면서 프로젝트에서 ES2015를 사용할 수 있습니다.

문서

저는 모든 프로젝트에 문서를 사용하는 것을 좋아합니다. 그러나 여기에는 많은 작업이 수반되므로 문서 작성이 지연되고 결국 잊혀지는 경우가 많습니다.

기본 정보

문서 작성은 프로젝트 이름, 설명 등 기본 정보부터 시작해야 합니다. 이는 다른 사람들이 코드베이스의 기능과 그것이 유용한지 여부를 이해하는 데 도움이 됩니다.

범위, 목표 등의 정보를 제공하여 사용자에게 더 나은 정보를 제공할 수 있고, 향후 새로운 변화가 무엇인지, 어떤 도움을 줄 수 있는지 사용자가 이해할 수 있도록 로드맵을 제공할 수 있습니다.

API, 튜토리얼 및 예제

물론 사용자가 코드 기반 사용 방법을 알 수 있도록 해야 합니다. 이는 API 문서부터 시작됩니다. 튜토리얼과 예제는 훌륭한 추가 기능이지만 이를 작성하는 것은 엄청난 작업이 될 수 있습니다. 그러나 인라인 문서에서는 그렇지 않습니다. 다음은 JSDoc

메타 작업

을 사용하여 구문 분석하고 문서 페이지로 변환할 수 있는 몇 가지 주석입니다. 일부 사용자는 코드 기반을 개선하기를 원합니다. 대부분의 경우 이는 기여된 코드이지만 일부는 개인용으로 사용자 정의 버전을 생성합니다. 이러한 사용자에게는 코드 베이스 구축, 테스트 실행, 데이터 생성, 변환 및 다운로드와 같은 메타 작업에 대한 문서를 제공하는 것이 도움이 됩니다.

기여

코드 베이스를 오픈 소스로 제공할 때 코드 기여를 받는 것이 도움이 됩니다. 기여자를 안내하기 위해 코드 기여 단계와 충족해야 하는 기준에 대한 일부 문서를 추가할 수 있습니다. 이는 기여된 코드와 올바른 기여 코드를 검토하고 승인하는 데 도움이 됩니다.

라이센스

마지막으로 라이센스를 사용하세요. 기술적으로 기술 라이센스를 선택하지 않더라도 코드 베이스는 여전히 저작권으로 보호되지만 모든 사람이 이를 아는 것은 아닙니다.

ChooseALicense.com이 법률 전문가가 아니더라도 라이센스를 선택할 수 있는 웹사이트라는 것을 알게 되었습니다. 라이선스를 선택한 후 프로젝트의 루트 디렉터리에 LICENSE.txt 파일을 추가하면 됩니다.

将它打包和发布到包管理器

对一个好的代码库来说,版本是很重要的。如果你想要加入重大的变化,用户可能需要保留他们现在正在使用的版本。

Semantic Versioning是流行的版本命名标准,或者叫它SemVer。SemVer版本包括三个数字,每一个代表不同程度的改变:重大改变,微小的改变和补丁

在你的Git仓库加入版本和发布

如果你有一个git仓库,你可以在你的仓库添加版本数字。你可以把它想象成你的仓库的快照。我们也叫它标签 Tags。可以通过开启终端和输入下面的文字来创造标签:

# git tag -a [version] -m [version message]
git tag -a v1.2.0 -m "Awesome Library v1.2.0"

很多类似GitHub的服务会提供关于所有版本的概览和提供它们的下载链接。

发布一个通用仓库

npm

许多编程语言自带有包管理器,或者是第三方包管理器。这可以允许我们下载关于这些语言的特定代码库。比如PHP的Composer 和Ruby的RubyGems

Node.js,一种独立的JavaScript引擎,拥有 npm,如果你对npm不熟悉,我们有一个很好的教程beginner’s guide。

默认情况下,你的npm包会发布为公共包。不要害怕,你也可以发布私有包 private packages, 设置一个私有的注册private registry, 或者根本不发布avoid publishing.

为了发布你的包,你的项目需要有一个 package.json 文件。你可以手动或者交互问答的方式来创建。通过输入下面的代码来开始问答:

`npm init`

这个版本属性需要跟你的git标签吻合。另外,请确定有README.md 文件。像是GitHub,npm在你的包的展示页使用它。

之后,你可以通过输入下面的代码来发布你的包:

`npm publish`

就是这样!你已经成功发布了你的npm包。

Bower

几年前,有另一个叫做Bower的包管理器。这个包管理器,实际上不是为了特定的语言准备的,而是为了互联网准备的。你可以发现大部分是前端资源。在Bower发布你的包的关键一点是你的代码库是否跟它兼容。

如果你对Bower不熟悉,我们也有一个教程beginner’s guide 。

跟npm一样,你也可以设置一个私有仓库private repository。你可以通过问答的方式避免发布。

有趣的是,在最近的一两年,很多人转为使用npm管理前端资源。近段npm包主要是跟JavaScript相关,大部分的前端资源也发布在了npm上。不管怎样,Bower仍然流行。我明确的推荐你在Bower上发布你的包。

我有提到Bower实际上是npm的一种模块,并最初是得到它的启发吗?它们的命令是很相似的,通过输入下面的代码产生bower.json文件:

`bower init`

跟npm init类似,指令是很直白的,最后,发布你的包:

`bower register awesomelib http://www.php.cn/`

像是把你的代码库放到了野外,任何人可以在他们的Node项目或者网络上使用它!

总结

核心的产品是库文件。确定它解决了问题,容易和适合使用,你会使得你的团队或者许多开发者变得高兴。

我提到的很多任务都是自动化的,比如:运行测试,创建标签,在package.json升级版本或者在npm或者bower重发布你的包。 这是你像Travis CI 或 Jenkins一样踏入持续集成和使用工具的开始。我之前提到的文章 article by Tim Evko 也讲述到了这点。

你构建和发布代码库了吗?请在下面的评论区分享!

 

以上就是设计和构建你自己的JavaScript代码库:提示与技巧的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.