การซ่อน / ปิดการใช้งานคุณสมบัติสำหรับผู้ใช้บางคน


11

ช่วยบอกว่าฉันมีแอพเวอร์ชันฟรีและจ่ายเงิน รุ่นที่ต้องชำระเงินเป็นชุดของรุ่นฟรีที่เกี่ยวกับคุณสมบัติที่ผู้ใช้มีความหมายว่ารุ่นที่จ่ายจะมีคุณสมบัติทั้งหมดของแอปฟรีพร้อมกับพิเศษ

มีรูปแบบการสลับความพร้อมใช้งานของคุณสมบัติตามธงที่โหลดเมื่อเริ่มต้น (เช่นฟรี / จ่ายเงิน) หรือไม่

ฉันไม่ชอบความคิดที่มีการติดตามรหัสในทุกที่:

if(isFreeVersion){
    // ...
} else {
    // ...
}

มี 2 สาขาคอมไพล์แยกต่างหากสำหรับทุกรุ่นไม่ได้ตัวเลือกเพราะมันจะหมายถึงการบำรุงรักษาที่ 2 (หรือมากกว่า) แหล่งที่มาของรหัสที่ดูเหมือนว่าทำไม่ได้ทั่วไปและมีการกล่าวถึงเพิ่มเติมได้ที่นี่: การดูแลรักษาทั้งสองรุ่นซอฟท์แวเฉพาะกิจจากที่เดียวกัน Codebase ในการควบคุมเวอร์ชัน

มีวิธีการทำเช่นนี้ในขณะที่ยังคงมีฐานรหัสเดียวและไม่ทิ้งรหัสด้วยคำสั่งแบบมีเงื่อนไขที่ตรวจสอบการตั้งค่าสถานะฟรี / ชำระเงิน

ฉันแน่ใจว่ามีการพูดคุยกันหลายครั้งก่อนหน้านี้และฉันแน่ใจว่ามีรูปแบบบางอย่างในการเข้าถึงปัญหานี้ แต่ฉันไม่พบมัน

เราใช้ Android / Java



@gnat tnx, ค้นหาดี แต่ฉันต้องการที่จะหารือเกี่ยวกับตัวเลือกที่ไม่ต้องการแยกสาขาและการบำรุงรักษารหัสหลายฐาน
Tadija Bagarić

2
ดูเหมือนว่าจะมีระดับการอนุญาตต่างกัน คุณอาจพิจารณาว่าปัญหานี้ได้รับการจัดการอย่างไรโดยทั่วไปแล้วจะมีคุณลักษณะเฉพาะสำหรับผู้ใช้ / บทบาทเท่านั้น
Bart van Ingen Schenau

@BartvanIngenSchenau ฉันพบว่าส่วนใหญ่จะเป็นการifตรวจสอบเพื่อซ่อนการควบคุมสำหรับคุณสมบัติที่ต้องห้ามหรือมีกล่องโต้ตอบป๊อปอัพเมื่อผู้ใช้พยายามทำสิ่งที่เขาไม่ได้รับอนุญาต ฉันหวังว่าจะหาวิธีหลีกเลี่ยงเงื่อนไขหลายอย่างในรหัส
Tadija Bagarić

2
ใช้ polyphormism คุณจะไม่ต้องถามตัวเองเกี่ยวกับเรื่องนี้อีกถ้ามีการแถลงอีกครั้งและจะรักษาได้ง่ายกว่ามาก!
Steve Chamaillard

คำตอบ:


9

หากคุณไม่ชอบif/elseบล็อกคุณสามารถ refactor ให้ใช้การสืบทอด (ดูแทนที่เงื่อนไขด้วย polymorphismจากหนังสือRefactoringของ Marin Fowler ) สิ่งนี้จะ:

  • ทำให้ง่ายขึ้นเล็กน้อยในการให้เหตุผลเกี่ยวกับรหัสของคุณ

  • ทำให้เป็นไปได้ที่จะมีสองคลาสหนึ่งสำหรับรุ่นฟรีและอีกรุ่นหนึ่งสำหรับรุ่นที่ต้องชำระเงินซึ่งจะส่งการเรียกไปยังชั้นเรียนอื่นเพื่อให้แน่ใจว่าความแตกต่างระหว่างรุ่นที่ให้บริการฟรีและที่จ่ายเงินนั้นถูก จำกัด ไว้ที่สองชั้น ชั้นฐาน)

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


3
ฉันคิดว่าคุณอาจต้องการที่ชัดเจนยิ่งขึ้นว่าการสืบทอดของการนำไปใช้ไม่จำเป็นสำหรับสิ่งนี้ ประโยชน์อีกอย่างคือแอพฟรีสามารถส่งได้โดยไม่มีคุณสมบัติพิเศษ การแก้ไขโค้ด Java byte เพื่อให้เงื่อนไข if เป็นจริงเสมอไม่ใช่เรื่องยากมาก
JimmyJames

15

เงื่อนไขที่ต้องการif(isFreeVersion)เกิดขึ้นเพียงครั้งเดียวในรหัส นี้ไม่ได้เป็นรูปแบบ แต่ผมแน่ใจว่าคุณรู้อยู่แล้วว่าชื่อของมันก็จะเรียกว่าหลักการแห้ง การมีรหัสอย่าง " if(isFreeVersion)" มากกว่าหนึ่งแห่งในรหัสของคุณหมายความว่าคุณทำซ้ำบรรทัดนี้ / ตรรกะในนั้นซึ่งหมายความว่าควรจะ refactored เพื่อหลีกเลี่ยงการซ้ำซ้อน

" if(isFreeVersion)" ควรจะใช้ในการตั้งค่ารายการของตัวเลือกการกำหนดค่าภายในสำหรับคุณสมบัติที่แตกต่างกัน โค้ดผลลัพธ์จะมีลักษณะดังนี้:

 if(isFreeVersion)
 {
      feature1Enabled=false;
      feature2Enabled=false;
      maxNoOfItems=5;
      advertisingStrategy=new ShowLotsOfAdvertisementsStrategy();
      // ...
 } 
 else
 {
      feature1Enabled=true;
      feature2Enabled=true;
      maxNoOfItems=int.MaxValue; // virtually unlimited
      advertisingStrategy=new ShowMinimalAdvertisementsStrategy();
 }

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

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

ในที่สุดเราก็มาดูบทความบล็อกของ Fowler เกี่ยวกับการสลับคุณสมบัติซึ่งเขาพูดถึงจุดเข้าใช้งาน / จุดสลับ ให้ฉันอ้างอิงจุดศูนย์กลางหนึ่งจุด:

อย่าพยายามปกป้องทุกเส้นทางของรหัสในฟีเจอร์โค้ดใหม่ด้วยการสลับ, เน้นเฉพาะจุดเข้าใช้งานที่จะนำผู้ใช้ไปที่นั่นและสลับจุดเข้าใช้งานเหล่านั้น

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


5
คุณได้แทนที่ IsFreeVersion ด้วย FeaturexEnabled โดยทั่วไปคุณไม่ได้ลดจำนวนการโทรลง ในขณะที่ฉันไม่ได้มีกรณีเช่นนั้นฉันได้จัดการสิ่งที่คล้ายกันเสมอโดยเมื่อสร้างเมนูปิดการใช้งานตัวเลือกเหล่านั้นที่ผู้ใช้ไม่ควรเห็น ส่วนใหญ่เป็นการสร้างแบบฟอร์ม แต่บางครั้งฉันก็ต้องทำเมื่อเตรียมเมนูป๊อปอัพ
Loren Pechtel

1
@ LorenPechtel: คุณควรอ่านคำตอบของฉันอีกครั้งอย่างระมัดระวังมากขึ้น ฉันพูดถึงสองสิ่งเพื่อลดจำนวนการทดสอบตามเงื่อนไขหนึ่งในนั้นคือหลักการ DRY หนึ่งในนั้นคือหนึ่งในนั้นเน้นการทดสอบใน UI และที่สำคัญการทำแผนที่ธงชาติ unspecific เช่นisFreeVersionการที่เฉพาะเจาะจงเอาคุณลักษณะพารามิเตอร์ต่างๆของความเจ็บปวดจากการทดสอบเหล่านั้น - พวกเขาจริงจะเริ่มต้นที่จะให้ความรู้สึกและไม่ได้ผลิตเป็นระเบียบในการบำรุงรักษาใด ๆ เพิ่มเติม
Doc Brown

6

มันดูเหมือนว่าฉันคำถามของคุณสามารถแก้ไขได้สวยดีใช้รูปแบบคุณลักษณะสลับ

บ่อยครั้งที่Pete Hodgson อธิบายไว้ในบทความเดียวในทุกสถานการณ์ที่คุณอาจเผชิญกับการใช้รูปแบบนี้ดีกว่าที่ฉันทำได้

นอกจากนี้ยังมีห้องสมุดบางแห่งที่รองรับรูปแบบนี้ ฉันมีประสบการณ์ทำงานกับFF4Jใน Java แต่ฉันจะเดาถ้าคุณพิมพ์:

feature toggle <whatever language you prefer>

... ในเครื่องมือค้นหาใด ๆ คุณจะได้รับโซลูชั่นมากมาย


2

มีมากกว่าหนึ่งวิธีในการบรรลุเป้าหมายนี้ วิธีที่ง่ายและตรงไปตรงมาคือการใช้รูปแบบสลับคุณสมบัติที่ให้ไว้ในบทความมากมาย วิธีการถัดไปเกี่ยวข้องกับการออกแบบสำหรับคุณสมบัติปลั๊กอิน ทั้ง Android และ IOS มีการชำระเงินในแอป พร้อมกับการชำระเงินที่เป็นไปได้สำหรับการดาวน์โหลด

เมื่อคุณดูที่ Servlets, JAMES Mailets และแม้แต่ปลั๊กอิน IDE พวกเขาทั้งหมดใช้แนวคิดของสถาปัตยกรรมปลั๊กอิน:

  • กำหนดอินเทอร์เฟซที่แอปของคุณรู้วิธีใช้ อินเทอร์เฟซนั้นจำเป็นต้องมีวิธีในการแทรกตัวเองลงในการนำทางแอปพลิเคชันของคุณและแอปอื่น ๆ ไปยังปลั๊กอินจุดสัมผัส
  • ตั้งค่าเส้นทางที่แอปของคุณจะอ่านเมื่อเริ่มต้นใช้งาน (การจัดการปลั๊กอินแบบรันไทม์นั้นยากกว่ามาก)
  • หากมีปลั๊กอินอยู่ (เช่นไฟล์ Java Jar) แอปจะอ่านรายการเพื่อค้นหาการนำไปใช้ของส่วนต่อประสานปลั๊กอินหรือสแกนคลาสที่ใช้อินเทอร์เฟซ
  • เมื่อพบคลาสแล้วจะมีการสร้างอินสแตนซ์และวิธีการที่เหมาะสมที่เรียกว่ารวมคุณสมบัติใหม่

สิ่งนี้ยังช่วยให้คุณมีโอกาสได้มีคุณสมบัติที่แตกต่างกันสำหรับผู้ชมที่แตกต่างกัน ผู้ใช้มีคุณสมบัติที่จ่ายเท่านั้น

รหัสแอปพลิเคชันของคุณได้รับการดูแลเป็นรหัสฐานเดียวและปลั๊กอินของคุณเป็นรหัสฐานแยกต่างหาก - แต่จะรวมเฉพาะส่วนที่เกี่ยวข้องกับปลั๊กอิน แอปรู้วิธีจัดการกับปลั๊กอินเมื่อมีอยู่และปลั๊กอินจะรู้วิธีโต้ตอบกับอินเทอร์เฟซเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.