คำถามติดแท็ก continuous-delivery

7
แสดงความคิดเห็นสิ่งที่ต้องทำด้วยกำหนดเวลา?
พื้นหลัง ฉันกำลังทำงานในทีมที่ต้องการปรับใช้การปรับใช้แบบไม่ต้องหยุดทำงาน เราวางแผนที่จะใช้กลยุทธ์การปรับใช้สีน้ำเงิน / เขียวเพื่อให้บรรลุเป้าหมายนี้ สิ่งหนึ่งที่ฉันตระหนักในการทำวิจัยคือความซับซ้อนของการเปลี่ยนแปลงฐานข้อมูล การดำเนินการอย่างง่ายเช่นการเปลี่ยนชื่อคอลัมน์อาจใช้เวลา3 รอบเต็มจนกว่าจะเสร็จสมบูรณ์! สำหรับฉันดูเหมือนว่าการมีการเปลี่ยนแปลงอย่างเต็มรูปแบบนั้นต้องใช้เวลาหลายรอบการเปิดตัวทำให้เกิดข้อผิดพลาดของมนุษย์ได้มาก ในบทความที่เชื่อมโยงมันแสดงให้เห็นว่าการเปลี่ยนแปลงรหัสมีความจำเป็นสำหรับ 2 รุ่นและการโยกย้ายฐานข้อมูลเป็นสิ่งจำเป็นสำหรับ 3 รุ่น สิ่งที่ฉันกำลังมองหา ในปัจจุบันหากเราต้องการจำบางสิ่งเราสามารถสร้างตั๋วในระบบการจัดการปัญหาของเราซึ่งสร้างความยุ่งเหยิงและอาจถูกย้ายไปที่การวิ่งในภายหลังหรือการค้างโดยผู้บริหาร หรือเราสามารถสร้างความคิดเห็นสิ่งที่ต้องทำซึ่งอาจจะถูกลืมไปโดยสิ้นเชิง สิ่งที่ฉันกำลังมองหาคือวิธีที่ความคิดเห็นของ TODO สามารถกำหนดเส้นตายได้และระบบการรวมอย่างต่อเนื่องของเรา (ไม่แน่ใจว่าเราจะใช้ในปัจจุบัน) จะปฏิเสธการสร้างหากกำหนดเวลานี้หมดอายุ ตัวอย่างเช่นถ้าเราเปลี่ยนชื่อคอลัมน์เราสามารถสร้างการโยกย้ายครั้งแรกสำหรับมันและจากนั้นสองความคิดเห็นสิ่งที่ต้องทำเพื่อให้แน่ใจว่าการย้ายสองที่เหลือจะถูกสร้างขึ้น: // TODO by v55: Create migration to move constraints to new column, remove references to old column in app // TODO by v56: Create migration to drop …

2
เหตุใด build.number“ การละเมิด” ของการกำหนดเวอร์ชันความหมาย?
ผมได้อธิบายที่เสนอสร้างระบบ (Gradle / Artifactory / เจนกินส์ / Chef) ให้เป็นหนึ่งในสถาปนิกอาวุโสของเราและเขาได้แสดงความคิดเห็นกับฉันว่าฉันเรียงลำดับของการไม่เห็นด้วย แต่ผมไม่ได้มีประสบการณ์มากพอที่จะจริงๆชั่งน้ำหนักใน โครงการนี้สร้างไลบรารี Java (JAR) เป็นสิ่งประดิษฐ์ที่ทีมอื่นนำมาใช้ซ้ำ สำหรับการกำหนดเวอร์ชันฉันต้องการใช้ความหมายของ: <major>.<minor>.<patch> โดยที่patchระบุถึงการแก้ไขบั๊ก / ฉุกเฉินminorระบุรีลีสที่เข้ากันได้แบบย้อนหลังและmajorบ่งชี้ถึงการปรับเปลี่ยนขนาดใหญ่ของ API และ / หรือการเปลี่ยนแปลงที่เข้ากันไม่ได้ด้านหลัง ตราบใดที่การส่งมอบตรงนี้คือสิ่งที่ฉันต้องการ: นักพัฒนาให้รหัสบางส่วน; สิ่งนี้ทริกเกอร์การสร้างสภาพแวดล้อม QA / TEST การทดสอบบางอย่างถูกเรียกใช้ (บางแบบอัตโนมัติและแบบทดสอบด้วยตนเอง) หากการทดสอบทั้งหมดผ่านไปแล้วบิลด์โปรดักชั่นจะเผยแพร่ JAR ไปยัง repo ภายในองค์กรของเรา ณ จุดนี้ JAR ควรได้รับการกำหนดเวอร์ชันอย่างถูกต้องและความคิดของฉันคือการใช้สิ่งbuild.numberที่สร้างขึ้นโดยอัตโนมัติและจัดทำโดยเครื่องมือ CI ของเราเพื่อทำหน้าที่เป็นหมายเลขโปรแกรมแก้ไข ดังนั้นการกำหนดเวอร์ชันจะเป็น: <major>.<minor>.<build.number> อีกครั้งที่build.numberมีให้โดยเครื่องมือ CI สถาปนิกปฏิเสธสิ่งนี้โดยบอกว่าการใช้หมายเลขการสร้าง CI นั้นเป็น "การละเมิด" …

2
เป็นการดีหรือไม่ที่จะเก็บหมายเลขเวอร์ชันของซอฟต์แวร์ใน VCS?
เวอร์ชันผลิตภัณฑ์เช่นv1.0.0.100ไม่เพียงแสดงถึงการผลิตซอฟต์แวร์ที่ไม่ซ้ำใคร แต่ช่วยระบุชุดคุณลักษณะและขั้นตอนการแก้ไขด่วนสำหรับผลิตภัณฑ์ดังกล่าว ตอนนี้ฉันเห็นสองวิธีในการรักษาแพ็กเกจ / build / ไบนารีเวอร์ชันสุดท้ายของผลิตภัณฑ์: การควบคุมเวอร์ชัน ไฟล์ที่เก็บหมายเลขรุ่น เซิร์ฟเวอร์การสร้างการรวมต่อเนื่อง (CI) จะมีสคริปต์เพื่อสร้างซอฟต์แวร์ที่ใช้หมายเลขรุ่นที่เช็คอินนี้เพื่อใช้กับทุกพื้นที่ของซอฟต์แวร์ที่ต้องการ (ไบนารีแพคเกจการติดตั้งหน้าช่วยเหลือเอกสาร ฯลฯ ) สภาพแวดล้อมและ / หรือสร้างพารามิเตอร์ สิ่งเหล่านี้ได้รับการดูแลรักษาไว้นอกการควบคุมเวอร์ชัน (เช่นไม่ได้เชื่อมโยงกับสแน็ปช็อต / แท็ก / สาขา) สคริปต์การสร้างกระจายและใช้หมายเลขในลักษณะเดียวกัน แต่พวกเขาเพิ่งได้รับค่าที่แตกต่างกัน (มันมีให้กับสคริปต์การสร้างแทนที่จะให้สคริปต์รู้ว่าจะรับได้ที่ไหนเทียบกับต้นไม้แหล่งที่มา) ปัญหาที่เกิดขึ้นกับวิธีแรกคือมันสามารถทำให้เกิดการผสมข้ามสาขาได้ยาก หากคุณยังคงรักษาซอฟต์แวร์รุ่นเดียวกันไว้ 2 ขนานคุณจะแก้ไขข้อขัดแย้งเมื่อรวมระหว่างการฉีดสองครั้งหากเวอร์ชันมีการเปลี่ยนแปลงทั้งคู่ตั้งแต่การรวมครั้งล่าสุด ปัญหาเกี่ยวกับวิธีการที่สองคือการกระทบยอด เมื่อคุณกลับไปที่การวางจำหน่าย 1 ปีที่ผ่านมาคุณจะพึ่งพาข้อมูลแท็กเพียงอย่างเดียวเพื่อระบุหมายเลขรุ่น ในทั้งสองกรณีอาจมีบางแง่มุมของหมายเลขเวอร์ชันที่ไม่ทราบก่อนสร้าง CI ตัวอย่างเช่นการสร้าง CI โดยทางโปรแกรมอาจใส่องค์ประกอบที่ 4 ซึ่งเป็นหมายเลขบิลด์อัตโนมัติ (เช่นบิลด์ที่ 140 ในสาขา) อาจเป็นหมายเลขการแก้ไขใน VCS วิธีที่ดีที่สุดในการติดตามหมายเลขเวอร์ชันของซอฟต์แวร์คืออะไร ควรรักษาชิ้นส่วน "รู้จัก" …

6
การจัดส่งต่อเนื่องสามารถทำงานในทางปฏิบัติได้อย่างไร
การส่งมอบอย่างต่อเนื่องฟังดูดี แต่ประสบการณ์การพัฒนาซอฟต์แวร์ของฉันหลายปีแนะนำว่าในทางปฏิบัติมันใช้งานไม่ได้ (แก้ไข: เพื่อให้ชัดเจนฉันมีการทดสอบจำนวนมากทำงานโดยอัตโนมัติคำถามของฉันคือการได้รับความมั่นใจในการส่งเช็คแต่ละครั้งซึ่งฉันเข้าใจว่าเป็นซีดีแบบเต็มรูปแบบทางเลือกไม่ใช่รอบปี . คือการทำซ้ำทุกสัปดาห์ (ซึ่งบางคนอาจพิจารณาว่ายังคงเป็นซีดีหากทำอย่างถูกต้อง) สองสัปดาห์หรือเดือนรวมถึงการประกันคุณภาพแบบโบราณในตอนท้ายของแต่ละการทดสอบเพิ่มเติมโดยอัตโนมัติ) ครอบคลุมการทดสอบเต็มรูปแบบเป็นไปไม่ได้ คุณต้องใส่จำนวนมาก - และเวลาคือเงิน - สำหรับทุกสิ่ง สิ่งนี้มีค่า แต่เวลาสามารถใช้เพื่อก่อให้เกิดคุณภาพในรูปแบบอื่น บางสิ่งยากที่จะทดสอบโดยอัตโนมัติ เช่น GUI แม้แต่ซีลีเนียมก็ยังไม่บอกคุณว่า GUI ของคุณสกปรกหรือไม่ การเข้าถึงฐานข้อมูลนั้นยากที่จะทดสอบโดยไม่ต้องติดตั้งขนาดใหญ่และแม้จะไม่ครอบคลุมกรณีมุมแปลก ๆ ในการจัดเก็บข้อมูลของคุณ ความปลอดภัยเช่นเดียวกันและสิ่งอื่น ๆ อีกมากมาย มีเพียงโค้ดเลเยอร์ธุรกิจเท่านั้นที่สามารถทดสอบหน่วยได้อย่างมีประสิทธิภาพ แม้แต่ในเลเยอร์ธุรกิจโค้ดส่วนใหญ่ไม่มีฟังก์ชั่นที่ง่ายซึ่งข้อโต้แย้งและค่าส่งคืนสามารถแยกได้ง่ายสำหรับการทดสอบ คุณสามารถใช้เวลาในการสร้างวัตถุจำลองซึ่งอาจไม่สอดคล้องกับการใช้งานจริง การรวมเข้ากับ / การทดสอบการทำงานเสริมการทดสอบหน่วย แต่สิ่งเหล่านี้ใช้เวลานานในการรัน (หากคุณไม่กำหนดค่าเริ่มต้นสภาพแวดล้อมการทดสอบจะไม่สอดคล้องกัน) การเปลี่ยนโครงสร้างใหม่หรือการเปลี่ยนแปลงอื่น ๆ จะทำลายการทดสอบมากมาย คุณใช้เวลามากมายในการแก้ไข หากเป็นเรื่องของการตรวจสอบการเปลี่ยนแปลงข้อมูลจำเพาะที่มีความหมายก็ถือว่าใช้ได้ แต่บ่อยครั้งที่การทดสอบหยุดชะงักเนื่องจากรายละเอียดการใช้งานในระดับต่ำที่ไม่มีความหมายไม่ใช่สิ่งที่ให้ข้อมูลที่สำคัญจริงๆ บ่อยครั้งที่การปรับเปลี่ยนนั้นมุ่งเน้นไปที่การทำงานซ้ำภายในของการทดสอบไม่ใช่การตรวจสอบฟังก์ชันการทำงานที่กำลังทดสอบอย่างแท้จริง รายงานภาคสนามเกี่ยวกับข้อผิดพลาดไม่สามารถจับคู่ได้อย่างง่ายดายกับรหัสรุ่นไมโครที่แม่นยำ

4
คุณควรเปลี่ยนมาใช้รุ่นบิลด์เมื่อไหร่
หนึ่งในแนวทางปฏิบัติที่กำหนดไว้ในการจัดส่งอย่างต่อเนื่องของ Jez Humble คือคุณควรสร้างแพ็คเกจหนึ่งและจากนั้นปล่อยให้แต่ละสภาพแวดล้อมที่คุณปรับใช้เพื่อให้การนำไปใช้งานและสิ่งประดิษฐ์ได้รับการทดสอบหลายครั้งก่อนที่จะทำการผลิต ฉันสนับสนุนแนวคิดนี้อย่างเต็มที่ ในทางกลับกันการสร้างโหมดดีบักที่ให้การติดตามสแต็กกับหมายเลขบรรทัดมีประโยชน์อย่างมากในสภาพแวดล้อมการทดสอบเช่นเดียวกับความสามารถในการดีบักแบบรีโมท แต่คุณต้องการส่งบิลด์ให้กับการผลิต ดังนั้นสำหรับผู้ที่ปฏิบัติตามหลักการแรกคุณจะสลับจากการดีบั๊กเป็นรีลีสบิลด์ในจุดใด เป็นก่อนการปรับใช้ครั้งแรกกับสภาพแวดล้อมการทดสอบการหาค่าใช้จ่ายของโหมดการดีบักที่เสียไปนั้นคุ้มค่าที่จะจ่ายเพื่อให้แน่ใจว่าคุณกำลังทดสอบผู้สมัครรุ่นจริงก่อนใครหรือไม่? หรือคุณจะสร้างอีกครั้งในขั้นตอนการโปรโมตโดยคิดว่าคุณจะเชื่อถือกระบวนการสร้างทับซอฟต์แวร์หรือไม่ หรือคุณเพียงแค่ขันมันทั้งหมดและปรับใช้เวอร์ชันการดีบักเพื่อการผลิต? หมายเหตุ: ฉันรู้ว่านี่ใช้ไม่ได้กับภาษาที่แปลความจริงเพราะโดยปกติแล้วคุณสามารถปัดสวิตช์ในการตั้งค่าแทนการทำในเวลาบิลด์

2
การย้ายฐานข้อมูลและสล็อตการปรับใช้ Azure
ฉันวางแผนที่จะส่งแอปพลิเคชันเว็บใหม่ไปยังบริการ Azure Web App (เว็บไซต์ Azure เดิม) ฉันต้องการใช้ประโยชน์จากสล็อตการปรับใช้เพื่อให้สามารถทดสอบการใช้งานของฉันก่อนที่จะผลักดันมันไปสู่การผลิต นั่นคือทั้งหมดที่ดีตราบใดที่ไม่มีการเปลี่ยนแปลง DB schema จำเป็นต้องใช้ แต่ถ้ามีการเปลี่ยนแปลงสกีมาฉันไม่สามารถมีซอฟต์แวร์เวอร์ชันสองเวอร์ชันที่ทำงานบน db เวอร์ชันเดียวกันได้ เนื่องจากฉันใช้ EF Migrations การกดไปที่สล็อตชั่วคราวจะส่งผลให้มีการอัปเดตฐานข้อมูลเป็นเวอร์ชันล่าสุดทันที ดังนั้นคำถามของฉันคือว่ามีการใช้สล็อตการปรับใช้ใด ๆ หรือไม่เมื่อต้องการโอนย้ายฐานข้อมูล ทำอย่างไรกับผู้ให้บริการ SaaS ขนาดใหญ่ พวกเขาทำการย้ายฐานข้อมูลทันทีด้วยเวอร์ชันใหม่หรือไม่ นั่นจะทำให้การหยุดทำงานของบางอย่างแน่นอน ฉันสามารถนึกถึงวิธีแก้ปัญหาที่ค่อนข้างซับซ้อนสำหรับปัญหานี้มีอะไรที่ง่ายบ้างไหม?

3
สร้างระบบอัตโนมัติและปรับใช้ระบบอัตโนมัติเทียบกับการรวมอย่างต่อเนื่อง
ฉันต้องการมีประสิทธิภาพมากขึ้นและต้องการใช้เครื่องมือ ops อย่างมีประสิทธิภาพ ด้วยความคิดนี้ฉันต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการรวมกลุ่มอย่างต่อเนื่อง แต่ดูเหมือนว่ามีหลายสิ่งที่เกี่ยวข้อง จริง ๆ แล้วฉันทำงานกับชุด Jetbrains ในงานของฉัน (IntelliJ, WebStorm ... ) ดังนั้นฉันจึงต้องการใช้พวกเขาต่อไปและฉันต้องการใช้ TeamCity ซึ่งดูเหมือนจะเป็นเครื่องมือที่ยอดเยี่ยมกับปลั๊กอินจำนวนมากสำหรับการรวมอย่างต่อเนื่อง ปัญหาของฉันคือฉันไม่รู้ว่าอะไรคือความแตกต่างระหว่าง: อาคารอัตโนมัติ (TeamCity เป็นซอฟต์แวร์ประเภทนี้): ฉันรู้ว่าเราสามารถสร้างแอปพลิเคชันของเราด้วยพื้นที่เก็บข้อมูล VCS ระยะไกลและมันยอดเยี่ยม แต่จุดประสงค์หลักของมันคืออะไร? ข้อมูลประเภทใดมีความสำคัญขณะทำสิ่งนี้ ที่จริงแล้วฉันรู้แล้วว่าซอฟต์แวร์ของฉันสร้างขึ้นหรือไม่อยู่ในพื้นที่และเพื่อนร่วมทีมของฉันด้วย ดังนั้นอะไรคือเป้าหมายของการใช้โดยไม่ต้องปรับใช้ระบบอัตโนมัติ? การปรับใช้ระบบอัตโนมัติ (TeamCity ดูเหมือนจะไม่ทำอย่างง่ายดาย) บูรณาการอย่างต่อเนื่อง (ซึ่งดูเหมือนว่าจะเป็นการรวมกันของทั้งสองข้างต้น) การจัดส่งอย่างต่อเนื่อง (นี่คืออะไรจริง ๆ ทำไมมันแตกต่างจากการรวมอย่างต่อเนื่อง?) คุณช่วยฉันเข้าใจเรื่องนี้ให้มากขึ้นได้ไหม?

4
ฉันจะเรียนรู้วิธีที่ถูกต้องในการใช้คุณสมบัติครึ่งหนึ่งได้อย่างไร [ปิด]
ปิด คำถามนี้จะต้องมีมากขึ้นมุ่งเน้น ไม่ยอมรับคำตอบในขณะนี้ ต้องการปรับปรุงคำถามนี้หรือไม่ อัปเดตคำถามเพื่อให้มุ่งเน้นที่ปัญหาเดียวโดยแก้ไขโพสต์นี้ ปิดให้บริการใน4 ปีที่แล้ว ฉันเป็นผู้นำทีมพัฒนาและฉันต้องการเผยแพร่ผลิตภัณฑ์ของเราบ่อยที่สุดเท่าที่จะเป็นไปได้ (การจัดส่งอย่างต่อเนื่อง) ในหลายกรณีเราต้องใช้คุณลักษณะที่ใช้เวลานานกว่าการนำไปใช้ในช่วงเวลาระหว่างการเผยแพร่ ฉันยังต้องการให้ผู้คนยอมรับรหัสของพวกเขาในชีวิตประจำวัน (Integration Integration) การใช้คุณลักษณะใหม่หลายครั้งต้องมีการเปลี่ยนแปลงคุณสมบัติที่มีอยู่และแน่นอนว่าคุณสมบัติที่มีอยู่ยังคงต้องทำงานแม้ว่าคุณสมบัติใหม่จะยังไม่เสร็จสิ้น หากผู้พัฒนาใช้วิธีการที่ถูกต้องพวกเขาสามารถปรับคุณสมบัติที่มีอยู่อย่างระมัดระวังและทั้งหมดข้างต้นไม่ใช่ปัญหา อย่างไรก็ตามวิธีการที่เหมาะสมคืออะไรจริง? ใจความพร้อมของฉันในการเขียนโปรแกรมบอกฉันว่าจะทำอย่างไรในแต่ละกรณี แต่ฉันต้องเรียนรู้เพิ่มเติมและฉันต้องการสื่อการอ่านที่ฉันสามารถอ่านและอ้างอิงสมาชิกในทีมเพื่ออ่าน หรือวิธีอื่นใดในการเรียนรู้วิธีที่ถูกต้องในการเรียนรู้วิธีนี้จะทำ นั่นคือคำถาม ฉันจะแน่ใจได้อย่างไรว่าสมาชิกในทีมเรียนรู้วิธีที่ถูกต้องในการนำคุณลักษณะครึ่งหนึ่งไปใช้ ฉันค้นหาคนที่อ้างว่ามีกลยุทธ์เกี่ยวกับเรื่องนี้ แต่ยังไม่พบยกเว้นคนที่เขียนความคิดแบบสุ่มเล็กน้อยในหัวข้อ บางทีฉันอาจไม่ได้ใช้คำค้นหาที่ถูกต้องหรืออาจไม่มีใครทำแนวทางที่เชื่อถือได้เกี่ยวกับเรื่องนี้

4
ความแตกต่างระหว่างสภาพแวดล้อม Staging และ UAT คืออะไร
ฉันรู้ว่าเราควรมีสภาพแวดล้อมที่แตกต่างกันอย่างน้อย 3 สภาพในขณะที่กำลังพัฒนาวิธีแก้ปัญหา: การพัฒนา : โปรแกรมเมอร์มีอิสระที่จะเปลี่ยนแปลงและผลักดันการเปลี่ยนแปลงได้ตลอดเวลาเพื่อทดสอบโค้ดของพวกเขาและรวมเข้ากับการเปลี่ยนแปลงอื่น ๆ ได้อย่างรวดเร็วโดยไม่ต้องกลัวว่าจะทำสิ่งใด - มันเชื่อมต่อกับฐานข้อมูลและบริการทดสอบ เอือด : ควรได้รับการปฏิบัติด้วยความเคารพจากนักพัฒนาเพราะมันควรจะมีสำเนา "ดีที่สุดเท่าที่จะเป็นไปได้" ของสภาพแวดล้อมการผลิตที่เกี่ยวข้องกับฮาร์ดแวร์ด้วยความแตกต่างที่ว่าสภาพแวดล้อมนี้เชื่อมต่อกับฐานข้อมูลของ UAT มันใช้ทั้งคำถามและคำตอบของทีมและผู้ใช้ในการตรวจสอบการเปลี่ยนแปลงที่จะไปสู่การผลิต การผลิต : เรื่องจริง ฉันได้ดูคำถามนี้เกี่ยวกับ SoftwareEngineeringและคำถามนี้ใน ServerFaultและพวกเขาดูเหมือนจะแตกต่างกันในความหมายของ Staging Environment นอกจากนี้หน้า Wikipediaเกี่ยวกับหัวเรื่องระบุว่า: การใช้งานหลักของสภาวะแวดล้อม staging คือการทดสอบสคริปต์และโพรซีเดอร์การติดตั้ง / คอนฟิกูเรชัน / การโอนย้ายทั้งหมดก่อนที่จะนำไปใช้กับสภาวะแวดล้อมการใช้งานจริง สิ่งนี้ทำให้มั่นใจได้ว่าการอัปเกรดหลักและรองทั้งหมดไปยังสภาพแวดล้อมการผลิตจะสมบูรณ์ได้อย่างน่าเชื่อถือโดยไม่มีข้อผิดพลาดในเวลาขั้นต่ำ สำหรับฉัน Staging เท่ากับ UAT ซึ่งคุณต้องทดสอบแอปพลิเคชันและขั้นตอนการปรับใช้ก่อนที่จะผลักดันสู่โลกแห่งความจริง ดังนั้นเราจึงผลักดันแพ็คเกจด้วยการเปลี่ยนแปลง UAT ในลักษณะเดียวกับที่เราผลักดันไปสู่การผลิตอัตโนมัติโดยสมบูรณ์และด้วยพิธีทั้งหมดที่เราควรมีกับสภาพแวดล้อมการผลิต ที่ถูกกล่าวว่าสิ่งที่แตกต่างที่เหมาะสมระหว่างสภาพแวดล้อม UAT และสภาพแวดล้อม Staging คืออะไร? - แก้ไข: …
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.