portaldacalheta.pt
  • หลัก
  • ทีมแบบกระจาย
  • เคล็ดลับและเครื่องมือ
  • ชีวิตนักออกแบบ
  • นวัตกรรม
ส่วนหลัง

การทำงานกับ TypeScript, Dependency Injection และ Discord Bots



ประเภทและรหัสที่ทดสอบได้ เป็นสองวิธีที่มีประสิทธิภาพที่สุดในการหลีกเลี่ยงข้อบกพร่องโดยเฉพาะอย่างยิ่งเมื่อรหัสเปลี่ยนแปลงไปตามกาลเวลา เราสามารถนำสองเทคนิคนี้ไปใช้กับการพัฒนา JavaScript โดยใช้ประโยชน์จากรูปแบบการออกแบบ TypeScript และรูปแบบการฉีดแบบพึ่งพา (DI) ตามลำดับ

เทมเพลตบูตสแตรปคืออะไร

ในบทช่วยสอน TypeScript นี้เราจะไม่กล่าวถึงพื้นฐานของ TypeScript โดยตรงยกเว้นการคอมไพล์ แต่เราจะสาธิตแนวทางปฏิบัติที่ดีที่สุดของ TypeScript แทนในขณะที่เราแนะนำวิธีการสร้างบอท Discord ตั้งแต่เริ่มต้นเชื่อมต่อการทดสอบและ DI และสร้างบริการตัวอย่าง เราจะใช้:



  • โหนด js
  • TypeScript
  • Discord.js ซึ่งเป็น Wrapper สำหรับ Discord API
  • InversifyJS เฟรมเวิร์กการฉีดแบบพึ่งพา
  • ไลบรารีการทดสอบ: Mocha, Chai และ ts-mockito
  • โบนัส: พังพอนและ MongoDB เพื่อเขียนการทดสอบการรวม

การตั้งค่าโครงการ Node.js ของคุณ

ก่อนอื่นมาสร้างไดเรกทอรีใหม่ชื่อ typescript-bot จากนั้นป้อนและสร้างโครงการ Node.js ใหม่โดยเรียกใช้:



npm init

หมายเหตุ: คุณสามารถใช้ yarn สำหรับสิ่งนั้น แต่เราจะยึดตาม npm เพื่อความกะทัดรัด



สิ่งนี้จะเปิดตัวช่วยสร้างแบบโต้ตอบซึ่งจะตั้งค่า package.json ไฟล์. คุณสามารถกดได้อย่างปลอดภัย ป้อน สำหรับคำถามทั้งหมด (หรือให้ข้อมูลบางอย่างหากคุณต้องการ) จากนั้นมาติดตั้งการอ้างอิงและการอ้างอิงเบี่ยงเบนของเรา (สิ่งที่จำเป็นสำหรับการทดสอบเท่านั้น)

npm i --save typescript discord.js inversify dotenv @types/node reflect-metadata npm i --save-dev chai mocha ts-mockito ts-node @types/chai @types/mocha

จากนั้นแทนที่สร้าง 'scripts' ส่วนใน package.json กับ:



'scripts': { 'start': 'node src/index.js', 'watch': 'tsc -p tsconfig.json -w', 'test': 'mocha -r ts-node/register 'tests/**/*.spec.ts'' },

เครื่องหมายคำพูดคู่รอบ tests/**/*.spec.ts จำเป็นในการค้นหาไฟล์แบบวนซ้ำ (หมายเหตุ: ไวยากรณ์อาจแตกต่างกันไปสำหรับนักพัฒนาที่ใช้ Windows)

start สคริปต์จะถูกใช้เพื่อเริ่มบอทซึ่งเป็น watch สคริปต์เพื่อคอมไพล์โค้ด TypeScript และ test เพื่อทำการทดสอบ



ตอนนี้ package.json ของเรา ไฟล์ควรมีลักษณะดังนี้:

{ 'name': 'typescript-bot', 'version': '1.0.0', 'description': '', 'main': 'index.js', 'dependencies': { '@types/node': '^11.9.4', 'discord.js': '^11.4.2', 'dotenv': '^6.2.0', 'inversify': '^5.0.1', 'reflect-metadata': '^0.1.13', 'typescript': '^3.3.3' }, 'devDependencies': { '@types/chai': '^4.1.7', '@types/mocha': '^5.2.6', 'chai': '^4.2.0', 'mocha': '^5.2.0', 'ts-mockito': '^2.3.1', 'ts-node': '^8.0.3' }, 'scripts': { 'start': 'node src/index.js', 'watch': 'tsc -p tsconfig.json -w', 'test': 'mocha -r ts-node/register 'tests/**/*.spec.ts'' }, 'author': '', 'license': 'ISC' }

การสร้างแอปพลิเคชันใหม่ในแดชบอร์ดแอป Discord

ในการโต้ตอบกับ Discord API เราจำเป็นต้องมีโทเค็น ในการสร้างโทเค็นดังกล่าวเราจำเป็นต้องลงทะเบียนแอปใน Discord Developer Dashboard ในการดำเนินการดังกล่าวคุณต้องสร้างบัญชี Discord แล้วไปที่ https://discordapp.com/developers/applications/ . จากนั้นคลิกไฟล์ แอปพลิเคชั่นใหม่ ปุ่ม:



ไม่ลงรอยกัน

เลือกชื่อและคลิก สร้าง . จากนั้นคลิก บอท → เพิ่มบ็อต และคุณทำเสร็จแล้ว มาเพิ่มบอทลงในเซิร์ฟเวอร์กัน แต่อย่าเพิ่งปิดหน้านี้เราจะต้องคัดลอกโทเค็นเร็ว ๆ นี้



เพิ่ม Discord Bot ของคุณไปยังเซิร์ฟเวอร์ของคุณ

ในการทดสอบบอทของเราเราจำเป็นต้องมีเซิร์ฟเวอร์ Discord คุณสามารถใช้เซิร์ฟเวอร์ที่มีอยู่หรือสร้างใหม่ ในการดำเนินการนี้ให้คัดลอก CLIENT_ID ของบ็อตที่พบในแท็บข้อมูลทั่วไปและใช้เป็นส่วนหนึ่งของสิ่งนี้ การอนุญาตพิเศษ URL:

https://discordapp.com/oauth2/authorize?client_id=&scope=bot



เมื่อคุณกด URL นี้ในเบราว์เซอร์แบบฟอร์มจะปรากฏขึ้นซึ่งคุณสามารถเลือกเซิร์ฟเวอร์ที่จะเพิ่มบอทได้

ข้อความต้อนรับ Standard Discord เพื่อตอบสนองต่อบอทของเราที่เข้าร่วมเซิร์ฟเวอร์

หลังจากที่คุณเพิ่มบอทลงในเซิร์ฟเวอร์ของคุณคุณจะเห็นข้อความดังที่กล่าวมา

node.js: javascript ฝั่งเซิร์ฟเวอร์

การสร้าง .env ไฟล์

เราต้องการวิธีบันทึกโทเค็นในแอปของเรา ในการดำเนินการดังกล่าวเราจะใช้ dotenv แพ็คเกจ ขั้นแรกรับโทเค็นจาก Discord Application Dashboard ( บอท → คลิกเพื่อเปิดเผย Token ):

ตอนนี้สร้าง .env จากนั้นคัดลอกและวางโทเค็นที่นี่:

TOKEN=paste.the.token.here

หากคุณใช้ Git ไฟล์นี้ควรอยู่ใน .gitignore เพื่อไม่ให้โทเค็นถูกบุกรุก สร้าง .env.example เพื่อให้ทราบว่า TOKEN ต้องการกำหนด:

TOKEN=

การคอมไพล์ TypeScript

ในการคอมไพล์ TypeScript คุณสามารถใช้ npm run watch คำสั่ง หรืออีกวิธีหนึ่งหากคุณใช้ PHPStorm (หรือ IDE อื่น) เพียงแค่ใช้โปรแกรมดูไฟล์จากปลั๊กอิน TypeScript และปล่อยให้ IDE ของคุณจัดการกับการคอมไพล์ มาทดสอบการตั้งค่าของเราโดยสร้าง src/index.ts ไฟล์ที่มีเนื้อหา:

console.log('Hello')

เรามาสร้าง tsconfig.json ไฟล์เหมือนด้านล่าง InversifyJS ต้องการ experimentalDecorators, emitDecoratorMetadata, es6 และ reflect-metadata:

{ 'compilerOptions': { 'module': 'commonjs', 'moduleResolution': 'node', 'target': 'es2016', 'lib': [ 'es6', 'dom' ], 'sourceMap': true, 'types': [ // add node as an option 'node', 'reflect-metadata' ], 'typeRoots': [ // add path to @types 'node_modules/@types' ], 'experimentalDecorators': true, 'emitDecoratorMetadata': true, 'resolveJsonModule': true }, 'exclude': [ 'node_modules' ] }

หากโปรแกรมดูไฟล์ทำงานอย่างถูกต้องควรสร้าง src/index.js ไฟล์และเรียกใช้ npm start ควรส่งผลให้:

> node src/index.js Hello

การสร้างคลาส Bot

ในที่สุดเรามาเริ่มใช้คุณลักษณะที่มีประโยชน์ที่สุดของ TypeScript: types ไปข้างหน้าและสร้างสิ่งต่อไปนี้ src/bot.ts ไฟล์:

import {Client, Message} from 'discord.js'; export class Bot { public listen(): Promise { let client = new Client(); client.on('message', (message: Message) => {}); return client.login('token should be here'); } }

ตอนนี้เราสามารถดูสิ่งที่เราต้องการได้ที่นี่โทเค็น! เราจะคัดลอกวางตรงนี้หรือโหลดค่าตรงจากสภาพแวดล้อม?

ทั้งสองอย่าง แต่เรามาเขียนโค้ดที่บำรุงรักษาขยายได้และทดสอบได้มากขึ้นโดยการฉีดโทเค็นโดยใช้ InversifyJS ของเรา

นอกจากนี้เราจะเห็นว่า Client การพึ่งพาเป็นฮาร์ดโค้ด เรากำลังจะฉีดตัวนี้เหมือนกัน

การกำหนดค่า Dependency Injection Container

ถึง ภาชนะฉีดพึ่งพา เป็นวัตถุที่รู้วิธีสร้างอินสแตนซ์วัตถุอื่น ๆ โดยทั่วไปเราจะกำหนดการอ้างอิงสำหรับแต่ละคลาสและคอนเทนเนอร์ DI จะดูแลการแก้ไข

InversifyJS แนะนำให้ใส่การอ้างอิงใน inversify.config.ts ดังนั้นเรามาเพิ่มคอนเทนเนอร์ DI ของเราที่นั่น:

import 'reflect-metadata'; import {Container} from 'inversify'; import {TYPES} from './types'; import {Bot} from './bot'; import {Client} from 'discord.js'; let container = new Container(); container.bind(TYPES.Bot).to(Bot).inSingletonScope(); container.bind(TYPES.Client).toConstantValue(new Client()); container.bind(TYPES.Token).toConstantValue(process.env.TOKEN); export default container;

นอกจากนี้ เอกสาร InversifyJS แนะนำ การสร้าง types.ts ไฟล์และรายชื่อแต่ละประเภทที่เราจะใช้ร่วมกับ Symbol ที่เกี่ยวข้อง สิ่งนี้ค่อนข้างไม่สะดวก แต่ช่วยให้มั่นใจได้ว่าจะไม่มีข้อขัดแย้งในการตั้งชื่อเมื่อแอปของเราเติบโตขึ้น แต่ละ Symbol เป็นตัวระบุที่ไม่ซ้ำกันแม้ว่าพารามิเตอร์คำอธิบายจะเหมือนกัน (พารามิเตอร์มีไว้เพื่อวัตถุประสงค์ในการดีบักเท่านั้น)

export const TYPES = { Bot: Symbol('Bot'), Client: Symbol('Client'), Token: Symbol('Token'), };

โดยไม่ต้องใช้ Symbol s นี่คือลักษณะที่เกิดขึ้นเมื่อเกิดความขัดแย้งในการตั้งชื่อ:

Error: Ambiguous match found for serviceIdentifier: MessageResponder Registered bindings: MessageResponder MessageResponder

ณ จุดนี้มันถึงแล้ว มากกว่า ไม่สะดวกในการจัดเรียงที่ MessageResponder ควรใช้โดยเฉพาะอย่างยิ่งถ้าคอนเทนเนอร์ DI ของเรามีขนาดใหญ่ การใช้ Symbol s ดูแลเรื่องนี้และเราไม่ได้มีตัวอักษรสตริงแปลก ๆ ในกรณีที่มีสองคลาสที่มีชื่อเดียวกัน

เอกสาร word xml คืออะไร

การใช้คอนเทนเนอร์ในแอป Discord Bot

ตอนนี้เรามาแก้ไข Bot ของเรา คลาสที่จะใช้คอนเทนเนอร์ เราต้องเพิ่ม @injectable และ @inject() คำอธิบายประกอบในการทำเช่นนั้น นี่คือใหม่ Bot ชั้น:

import {Client, Message} from 'discord.js'; import {inject, injectable} from 'inversify'; import {TYPES} from './types'; import {MessageResponder} from './services/message-responder'; @injectable() export class Bot { private client: Client; private readonly token: string; constructor( @inject(TYPES.Client) client: Client, @inject(TYPES.Token) token: string ) { this.client = client; this.token = token; } public listen(): Promise { this.client.on('message', (message: Message) => { console.log('Message received! Contents: ', message.content); }); return this.client.login(this.token); } }

สุดท้ายมาสร้างอินสแตนซ์บอทของเราใน index.ts ไฟล์:

require('dotenv').config(); // Recommended way of loading dotenv import container from './inversify.config'; import {TYPES} from './types'; import {Bot} from './bot'; let bot = container.get(TYPES.Bot); bot.listen().then(() => { console.log('Logged in!') }).catch((error) => { console.log('Oh no! ', error) });

ตอนนี้เริ่มบอทและเพิ่มลงในเซิร์ฟเวอร์ของคุณ จากนั้นหากคุณพิมพ์ข้อความในช่องเซิร์ฟเวอร์ข้อความนั้นควรปรากฏในบันทึกบนบรรทัดคำสั่งดังนี้:

> node src/index.js Logged in! Message received! Contents: Test

ในที่สุดเราก็มีการตั้งค่าพื้นฐาน: ประเภท TypeScript และคอนเทนเนอร์การฉีดพึ่งพาภายในบอทของเรา

การใช้ตรรกะทางธุรกิจ

ตรงไปที่เนื้อหาหลักของบทความนี้นั่นคือการสร้างโค้ดเบสที่สามารถทดสอบได้ ในระยะสั้นโค้ดของเราควรใช้แนวทางปฏิบัติที่ดีที่สุด (เช่น ของแข็ง ) ไม่ซ่อนการอ้างอิงไม่ใช้วิธีการคงที่

นอกจากนี้ ไม่ควรทำให้เกิดผลข้างเคียงเมื่อทำงานและสามารถล้อเลียนได้ง่าย .

เพื่อความเรียบง่ายบอทของเราจะทำเพียงสิ่งเดียว: มันจะค้นหาข้อความที่เข้ามาและหากมีคำว่า 'ping' เราจะใช้คำสั่งบอท Discord ที่มีอยู่คำสั่งหนึ่งเพื่อให้บอทตอบสนองด้วย 'pong! ” ให้กับผู้ใช้นั้น

เพื่อแสดงวิธีการฉีดออบเจ็กต์แบบกำหนดเองลงใน Bot ออบเจ็กต์และทดสอบหน่วยเราจะสร้างสองคลาส: PingFinder และ MessageResponder. เราจะฉีด MessageResponder ลงใน Bot ชั้นเรียนและ PingFinder เป็น MessageResponder.

นี่คือ src/services/ping-finder.ts ไฟล์:

import {injectable} from 'inversify'; @injectable() export class PingFinder { private regexp = 'ping'; public isPing(stringToSearch: string): boolean { return stringToSearch.search(this.regexp) >= 0; } }

จากนั้นเราฉีดคลาสนั้นลงใน src/services/message-responder.ts ไฟล์:

วิธีการเริ่มโครงการ angularjs
import {Message} from 'discord.js'; import {PingFinder} from './ping-finder'; import {inject, injectable} from 'inversify'; import {TYPES} from '../types'; @injectable() export class MessageResponder { private pingFinder: PingFinder; constructor( @inject(TYPES.PingFinder) pingFinder: PingFinder ) { this.pingFinder = pingFinder; } handle(message: Message): Promise { if (this.pingFinder.isPing(message.content)) { return message.reply('pong!'); } return Promise.reject(); } }

สุดท้ายนี่คือการแก้ไข Bot ซึ่งใช้ MessageResponder ชั้น:

import {Client, Message} from 'discord.js'; import {inject, injectable} from 'inversify'; import {TYPES} from './types'; import {MessageResponder} from './services/message-responder'; @injectable() export class Bot { private client: Client; private readonly token: string; private messageResponder: MessageResponder; constructor( @inject(TYPES.Client) client: Client, @inject(TYPES.Token) token: string, @inject(TYPES.MessageResponder) messageResponder: MessageResponder) { this.client = client; this.token = token; this.messageResponder = messageResponder; } public listen(): Promise { this.client.on('message', (message: Message) => { if (message.author.bot) { console.log('Ignoring bot message!') return; } console.log('Message received! Contents: ', message.content); this.messageResponder.handle(message).then(() => { console.log('Response sent!'); }).catch(() => { console.log('Response not sent.') }) }); return this.client.login(this.token); } }

ในสถานะนั้นแอปจะไม่สามารถทำงานได้เนื่องจากไม่มีคำจำกัดความสำหรับ MessageResponder และ PingFinder ชั้นเรียน มาเพิ่มสิ่งต่อไปนี้ใน inversify.config.ts ไฟล์:

container.bind(TYPES.MessageResponder).to(MessageResponder).inSingletonScope(); container.bind(TYPES.PingFinder).to(PingFinder).inSingletonScope();

นอกจากนี้เราจะเพิ่มสัญลักษณ์ประเภทให้กับ types.ts:

MessageResponder: Symbol('MessageResponder'), PingFinder: Symbol('PingFinder'),

ตอนนี้หลังจากรีสตาร์ทแอปบอทควรตอบกลับทุกข้อความที่มี 'ping':

บอทตอบสนองต่อข้อความที่มีคำ

และนี่คือลักษณะที่ปรากฏในบันทึก:

> node src/index.js Logged in! Message received! Contents: some message Response not sent. Message received! Contents: message with ping Ignoring bot message! Response sent!

การสร้างการทดสอบหน่วย

ตอนนี้เราได้ฉีดการอ้างอิงอย่างถูกต้องแล้วการเขียนการทดสอบหน่วยก็ทำได้ง่าย เราจะใช้ Chai และ ts-mockito สำหรับสิ่งนั้น อย่างไรก็ตามยังมีนักวิ่งทดสอบและห้องสมุดจำลองอื่น ๆ อีกมากมายที่คุณสามารถใช้ได้

ไวยากรณ์การเยาะเย้ยใน ts-mockito ค่อนข้างละเอียด แต่ยังเข้าใจง่าย วิธีตั้งค่า MessageResponder บริการและฉีด PingFinder เยาะเย้ยมัน:

let mockedPingFinderClass = mock(PingFinder); let mockedPingFinderInstance = instance(mockedPingFinderClass); let service = new MessageResponder(mockedPingFinderInstance);

ตอนนี้เราได้ตั้งค่าการล้อเลียนแล้วเราสามารถกำหนดผลลัพธ์ของ isPing() ได้ ควรโทรและยืนยัน reply() โทร. ประเด็นก็คือในการทดสอบหน่วยเรากำหนดผลลัพธ์ของ isPing() โทร: true หรือ false. ไม่สำคัญว่าเนื้อหาของข้อความจะเป็นอย่างไรดังนั้นในการทดสอบเราใช้ 'Non-empty string'

when(mockedPingFinderClass.isPing('Non-empty string')).thenReturn(true); await service.handle(mockedMessageInstance) verify(mockedMessageClass.reply('pong!')).once();

ชุดทดสอบทั้งหมดมีลักษณะดังนี้:

import 'reflect-metadata'; import 'mocha'; import {expect} from 'chai'; import {PingFinder} from '../../../src/services/ping-finder'; import {MessageResponder} from '../../../src/services/message-responder'; import {instance, mock, verify, when} from 'ts-mockito'; import {Message} from 'discord.js'; describe('MessageResponder', () => { let mockedPingFinderClass: PingFinder; let mockedPingFinderInstance: PingFinder; let mockedMessageClass: Message; let mockedMessageInstance: Message; let service: MessageResponder; beforeEach(() => { mockedPingFinderClass = mock(PingFinder); mockedPingFinderInstance = instance(mockedPingFinderClass); mockedMessageClass = mock(Message); mockedMessageInstance = instance(mockedMessageClass); setMessageContents(); service = new MessageResponder(mockedPingFinderInstance); }) it('should reply', async () => { whenIsPingThenReturn(true); await service.handle(mockedMessageInstance); verify(mockedMessageClass.reply('pong!')).once(); }) it('should not reply', async () => { whenIsPingThenReturn(false); await service.handle(mockedMessageInstance).then(() => { // Successful promise is unexpected, so we fail the test expect.fail('Unexpected promise'); }).catch(() => { // Rejected promise is expected, so nothing happens here }); verify(mockedMessageClass.reply('pong!')).never(); }) function setMessageContents() { mockedMessageInstance.content = 'Non-empty string'; } function whenIsPingThenReturn(result: boolean) { when(mockedPingFinderClass.isPing('Non-empty string')).thenReturn(result); } });

การทดสอบสำหรับ PingFinder ค่อนข้างเป็นเรื่องเล็กน้อยเนื่องจากไม่มีการอ้างอิงที่จะล้อเลียน นี่คือกรณีทดสอบตัวอย่าง:

describe('PingFinder', () => { let service: PingFinder; beforeEach(() => { service = new PingFinder(); }) it('should find 'ping' in the string', () => { expect(service.isPing('ping')).to.be.true }) });

การสร้างการทดสอบการรวม

นอกจากการทดสอบหน่วยแล้วเรายังสามารถเขียนการทดสอบการบูรณาการได้อีกด้วย ความแตกต่างที่สำคัญคือการอ้างอิงในการทดสอบเหล่านั้นไม่ได้ถูกล้อเลียน อย่างไรก็ตามมีการอ้างอิงบางอย่างที่ไม่ควรทดสอบเช่นการเชื่อมต่อ API ภายนอก ในกรณีนี้เราสามารถสร้าง mocks และ rebind ไปยังภาชนะบรรจุเพื่อให้เครื่องจำลองถูกฉีดเข้าไปแทน ตัวอย่างวิธีการดำเนินการดังต่อไปนี้:

การประเมินฮิวริสติกคืออะไร
import container from '../../inversify.config'; import {TYPES} from '../../src/types'; // ... describe('Bot', () => { let discordMock: Client; let discordInstance: Client; let bot: Bot; beforeEach(() => { discordMock = mock(Client); discordInstance = instance(discordMock); container.rebind(TYPES.Client) .toConstantValue(discordInstance); bot = container.get(TYPES.Bot); }); // Test cases here });

สิ่งนี้นำเราไปสู่ตอนท้ายของบทช่วยสอนบอท Discord ของเรา ขอแสดงความยินดีคุณสร้างมันขึ้นมาอย่างหมดจดโดยมี TypeScript และ DI มาตั้งแต่เริ่มต้น! ตัวอย่างการฉีดการพึ่งพา TypeScript นี้เป็นรูปแบบที่คุณสามารถเพิ่มลงในละครของคุณเพื่อใช้กับโปรเจ็กต์ใด ๆ

TypeScript และ Dependency Injection: ไม่เพียง แต่สำหรับการพัฒนา Discord Bot

นำโลกเชิงวัตถุของ TypeScript ใน JavaScript เป็นการเพิ่มประสิทธิภาพที่ดีเยี่ยมไม่ว่าเราจะทำงานกับโค้ดส่วนหน้าหรือส่วนหลัง เพียงแค่ใช้ประเภทเพียงอย่างเดียวทำให้เราหลีกเลี่ยงจุดบกพร่องต่างๆได้ การมีการฉีดขึ้นต่อกันใน TypeScript จะช่วยผลักดันแนวทางปฏิบัติที่ดีที่สุดในเชิงวัตถุให้มากขึ้นในการพัฒนาที่ใช้ JavaScript

แน่นอนว่าเนื่องจากข้อ จำกัด ของภาษามันจะไม่ง่ายและเป็นธรรมชาติเท่ากับภาษาที่พิมพ์แบบคงที่ แต่สิ่งหนึ่งที่แน่นอนคือ TypeScript การทดสอบหน่วยและการฉีดขึ้นต่อกันทำให้เราสามารถเขียนโค้ดที่อ่านได้ง่ายขึ้นควบคู่กันและดูแลรักษาได้มากขึ้นไม่ว่าเราจะพัฒนาแอปประเภทใดก็ตาม

ที่เกี่ยวข้อง: สร้าง WhatsApp Chatbot ไม่ใช่แอป

ทำความเข้าใจพื้นฐาน

ทำไมฉันจึงควรใช้การฉีดแบบพึ่งพา?

คุณควรใช้รูปแบบการออกแบบการฉีดแบบพึ่งพาหากคุณต้องการเขียนโค้ดที่สะอาดยิ่งขึ้นในแง่ที่ว่าสามารถทดสอบหน่วยได้บำรุงรักษาได้มากกว่าและทำงานควบคู่กันอย่างหลวม ๆ ด้วยการใช้การฉีดแบบพึ่งพาคุณจะมีสูตรสำหรับรหัสที่สะอาดขึ้นโดยไม่ต้องสร้างล้อใหม่

การฉีดแบบพึ่งพามีประโยชน์อย่างไร?

เราถูกบังคับให้เขียนโค้ดที่ทดสอบหน่วยได้ซึ่งง่ายต่อการบำรุงรักษา การอ้างอิงถูกฉีดผ่านตัวสร้างและสามารถจำลองได้ง่ายในการทดสอบหน่วย นอกจากนี้รูปแบบนี้สนับสนุนให้เราเขียนโค้ดคู่กันอย่างหลวม ๆ

วัตถุประสงค์ของ TypeScript คืออะไร?

วัตถุประสงค์หลักของ TypeScript คือเพื่อให้โค้ด JavaScript ที่สะอาดและอ่านง่ายขึ้นโดยการเพิ่มประเภท เป็นตัวช่วยสำหรับนักพัฒนาซึ่งส่วนใหญ่มีประโยชน์ใน IDE ภายใต้ฝากระโปรง TypeScript ยังคงถูกแปลงเป็น JavaScript ธรรมดา

บอท Discord คืออะไร?

บอท Discord เป็นเว็บแอปที่ใช้ Discord API สำหรับการสื่อสาร

บอท Discord ทำอะไรได้บ้าง?

บอท Discord สามารถตอบสนองต่อข้อความกำหนดบทบาทตอบสนองด้วยปฏิกิริยาและอื่น ๆ มีเมธอด API สำหรับการกระทำที่ไม่ลงรอยกันที่ผู้ใช้ทั่วไปและผู้ดูแลระบบสามารถทำได้

TypeScript มีประโยชน์อย่างไร?

ประโยชน์หลักของ TypeScript คือช่วยให้นักพัฒนาสามารถกำหนดและใช้ประเภทได้ ด้วยการใช้คำแนะนำประเภททรานสไพเลอร์ (หรือ“ คอมไพเลอร์ต้นทางไปยังแหล่งที่มา”) จะรู้ว่าอ็อบเจ็กต์ชนิดใดควรถูกส่งไปยังเมธอด ตรวจพบข้อผิดพลาดหรือการโทรที่ไม่ถูกต้องในเวลาคอมไพล์ซึ่งทำให้เกิดข้อบกพร่องน้อยลงบนเซิร์ฟเวอร์ที่ใช้งานจริง

การเปรียบเทียบสัญญา Node.js

แบ็คเอนด์

การเปรียบเทียบสัญญา Node.js
การสร้างแอป Vue.js ที่แสดงผลฝั่งเซิร์ฟเวอร์โดยใช้ Nuxt.js

การสร้างแอป Vue.js ที่แสดงผลฝั่งเซิร์ฟเวอร์โดยใช้ Nuxt.js

ส่วนหน้าของเว็บ

โพสต์ยอดนิยม
เอกสาร Agile: การปรับสมดุลความเร็วและการรักษาความรู้
เอกสาร Agile: การปรับสมดุลความเร็วและการรักษาความรู้
ทำลายหลักการออกแบบ (ด้วยอินโฟกราฟิก)
ทำลายหลักการออกแบบ (ด้วยอินโฟกราฟิก)
วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ
วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ
ฮาร์ดแวร์ที่คล่องตัวพร้อมการพัฒนาซอฟต์แวร์ในตัว
ฮาร์ดแวร์ที่คล่องตัวพร้อมการพัฒนาซอฟต์แวร์ในตัว
วิธีการรวม OAuth 2 เข้ากับ Django / DRF Back-end ของคุณโดยไม่บ้า
วิธีการรวม OAuth 2 เข้ากับ Django / DRF Back-end ของคุณโดยไม่บ้า
 
GWT Toolkit: สร้างส่วนหน้า JavaScript ที่มีประสิทธิภาพโดยใช้ Java
GWT Toolkit: สร้างส่วนหน้า JavaScript ที่มีประสิทธิภาพโดยใช้ Java
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
Libation Frontiers: เจาะลึกอุตสาหกรรมไวน์โลก
Libation Frontiers: เจาะลึกอุตสาหกรรมไวน์โลก
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
พบกับ Phoenix: กรอบงานคล้ายรางสำหรับเว็บแอปสมัยใหม่บน Elixir
พบกับ Phoenix: กรอบงานคล้ายรางสำหรับเว็บแอปสมัยใหม่บน Elixir
โพสต์ยอดนิยม
  • เมื่อข้อมูลในตารางซ้ำซ้อน
  • การจัดการข้อผิดพลาดในการโทรกลับของโหนด js
  • แนวปฏิบัติที่ดีที่สุดของผังบัญชี
  • วิธีรับทวีตจาก twitter api ใน python
  • วิธีรับเทอร์มินัลบลูมเบิร์ก
  • การจัดการข้อยกเว้นในสปริง mvc
  • กวดวิชาการทดสอบหน่วยสตูดิโอภาพ
หมวดหมู่
  • ทีมแบบกระจาย
  • เคล็ดลับและเครื่องมือ
  • ชีวิตนักออกแบบ
  • นวัตกรรม
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt