วิธีนี้ในการเรียกฟังก์ชั่นเป็นการฝึกที่ไม่ดีหรือไม่?


10

ฉันมีรหัสต่อไปนี้:

public void moveCameraTo(Location location){
    moveCameraTo(location.getLatitude(), location.getLongitude());
}

public void moveCameraTo(double latitude, double longitude){
    LatLng latLng = new LatLng(latitude, longitude);
    moveCameraTo(latLng);
}

public void moveCameraTo(LatLng latLng){
    GoogleMap googleMap =  getGoogleMap();
    cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, INITIAL_MAP_ZOOM_LEVEL);
    googleMap.moveCamera(cameraUpdate);
}

ฉันคิดว่าด้วยวิธีนี้ฉันกำจัดความรับผิดชอบในการรู้ว่าสิ่งที่อยู่LatLngในชั้นเรียนอื่นเช่น

และคุณไม่จำเป็นต้องเตรียมข้อมูลก่อนเรียกฟังก์ชั่น

คุณคิดอย่างไร?

วิธีนี้มีชื่อหรือไม่? เป็นการฝึกที่ไม่ดีจริง ๆ หรือ?


2
ฉันคิดว่าคุณเพิ่งจัดการกับ Encapsulation โดยใช้วิธีการโอเวอร์โหลดในตัวของภาษา มันไม่ดี / ไม่ดี เป็นเครื่องมือที่สามารถช่วยหรือทำให้โค้ดของคุณเสียหาย
bitsoflogic

5
ถ้าเป้าหมายของคุณคือการปกปิดLatLngจากลูกค้าของเรื่องนี้Cameraระดับแล้วคุณอาจไม่ต้องการเป็นmoveCameraTo(LatLng) public
bitsoflogic

นอกเหนือจากคำแนะนำที่ให้ไว้ในคำตอบแล้วนี่เป็นสถานที่ที่เหมาะสำหรับการพูดถึง YAGNI คุณจะไม่ต้องการมัน อย่ากำหนดวิธีการ API ก่อนที่จะมีกรณีการใช้งานที่ดีเพราะ ... คุณไม่ต้องการมัน
Patrick Hughes

ไม่มีอะไรผิดปกติกับmoveCameraToLocationและ/moveCameraTo moveCameraToCoordsแน่นอนว่าไม่ต้องการผ่านตำแหน่ง / lat / long ทั้งหมดในชื่อเดียวกัน
insidesin

คำตอบ:


9

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

กลิ่นรหัสที่นี่จะเป็นถ้าคุณให้ขยายวิธีการโทรวิธี วิธีการถ่ายที่ตั้งจะเรียกวิธีการถ่ายภาพสองครั้งซึ่งเรียกว่าวิธีการถ่าย latLng ซึ่งจะเรียกสิ่งที่รู้วิธีปรับปรุงกล้อง

โซ่ยาวมีความแข็งแกร่งเท่ากับจุดอ่อนของมันเท่านั้น ส่วนขยายของลูกโซ่แต่ละเส้นจะเพิ่มส่วนแบ่งของโค้ดที่ต้องทำงานหรือสิ่งนี้แตก

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

ทำแบบนั้นและคุณสามารถลบออกได้โดยไม่ทำลายอีกครึ่งหนึ่ง

พิจารณา:

public void moveCameraTo(Location location){
    moveCameraTo( new LatLng(location) );
}

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

หากLocationสามารถปรับเปลี่ยนได้ แต่LatLngไม่ใช่ลองแก้ไขด้วยการเพิ่มโรงงานลงในLocation:

moveCameraTo( location.ToLatLng() );

นอกจากนี้ยังหลีกเลี่ยงความหลงไหลในแบบดั้งเดิม


1
ดูเหมือนจะไม่เลวสำหรับฉัน - เป็นเพียงความสะดวกสบายสำหรับผู้บริโภค หากสิ่งนี้ถูกล่ามโซ่ 10 ครั้งหรือหากผู้บริโภคไม่ต้องการตัวเลือกเหล่านี้ทั้งหมดฉันก็จะเรียกมันว่ากลิ่นรหัส
mcknz

1
แต่อะไรคือทางเลือกที่ทำให้ตรรกะทั้งหมดสำหรับการแปลงคู่เป็น LagLng หรือ Location to LagLng ในแต่ละฟังก์ชัน?
Tlaloc-ES

@ Tlaloc-ES ดีขึ้นหรือไม่
candied_orange

@ Tlaloc-ES "เปลี่ยน" จะต้องเกิดขึ้นเพียงครั้งเดียวเมื่อดั้งเดิมถูกโหลดลงในตรรกะโดเมน มันจะเกิดขึ้นเมื่อคุณทำลาย DTO จากนั้นตรรกะโดเมนทั้งหมดของคุณจะผ่านLatLngหรือLocationวัตถุ คุณสามารถแสดงความสัมพันธ์ระหว่างทั้งสองด้วยNew LatLng(Location)หรือLocation.toLatLng()ถ้าคุณต้องการที่จะไปจากที่หนึ่งไปยังอีก
bitsoflogic

1
@ Tlaloc-ES การอ่านที่เกี่ยวข้อง: FlagArgumentโดย Martin Fowler อ่านส่วน "การใช้งานแบบ Tangled"
Marc.2377

8

ไม่มีอะไรผิดปกติกับโซลูชันของคุณ

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

รหัสvoid moveCameraTo(double latitude, double longitude)ไม่ได้ทำให้รหัสง่ายขึ้นอย่างที่ฉันเห็นไม่มีปัญหาเพียงแค่เรียกmoveCameraTo(new LatLng(latitude, longitude));มัน วิธีนี้ยังมีกลิ่นของความหลงใหลดั้งเดิม

void moveCameraTo(Location location)สามารถแก้ไขได้ดีกว่าโดยการพิสูจน์และวิธีการเรียกLocation.ToLatLng()moveCameraTo(location.ToLatLng())

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

ฉันคิดว่าด้วยวิธีนี้ฉันจะกำจัดความรับผิดชอบในการรู้ว่า LatLng ในคลาสอื่นเป็นอย่างไร

ฉันไม่เห็นเหตุผลว่าทำไมนี่จึงเป็นปัญหา ตราบใดที่ระดับอ้างอิงรหัสของคุณที่มีก็ยังคงขึ้นอยู่กับทางอ้อมvoid moveCameraTo(LatLng latLng) LatLngแม้ว่าคลาสนั้นจะไม่ยกตัวอย่างโดยตรง

และคุณไม่จำเป็นต้องเตรียมข้อมูลก่อนเรียกฟังก์ชั่น

ฉันไม่เข้าใจว่าคุณหมายถึงอะไร ถ้ามันหมายถึงการสร้างอินสแตนซ์ใหม่หรือเปลี่ยนคลาสจากที่หนึ่งเป็นอีกแบบฉันไม่เห็นปัญหาเลย

เมื่อคิดถึงมันแล้วฉันรู้สึกว่าสิ่งที่ฉันพูดนั้นได้รับการสนับสนุนจากการออกแบบ API ของ. NET ด้วยเช่นกัน ในอดีตแล้วคลาสของ. NET จำนวนมากนั้นใช้วิธีการของคุณในการมีโอเวอร์โหลดจำนวนมากพร้อมพารามิเตอร์ที่แตกต่างกันและการแปลงภายในอย่างง่าย ๆ แต่นั่นคือก่อนที่วิธีการขยายมีอยู่ คลาส NET ที่ทันสมัยกว่านั้นมีน้ำหนักเบากว่าใน API ของตนเองและหากมีวิธีใด ๆ ที่มีพารามิเตอร์มากเกินไปจะมีการจัดเตรียมเป็นวิธีส่วนขยาย ตัวอย่างที่เก่ากว่าคือNLog ILoggerที่มีโอเวอร์โหลดจำนวนมากสำหรับการเขียนเพื่อบันทึก เปรียบเทียบกับMicrosoft.Extensions.Logging.ILogger ที่ใหม่กว่าซึ่งมีทั้งหมด 3 วิธี (และมีเพียง 1 ถ้าคุณนับการบันทึกเอง) แต่มีจำนวนมากของผู้ช่วยเหลือและ parametrizations ต่างๆเป็นวิธีการขยาย

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


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

@candied_orange ขวา ตอนนี้ฉันดูคำถามของ OP ได้ดีขึ้นซึ่งดูเหมือน Java มากกว่า C #
ร่าเริง

ฉันคิดว่ามันไม่ได้มีปัญหาในการใช้งานmoveCameraTo(new LatLng(latitude, longitude));ในที่ใด ๆ ของโครงการ แต่ฉันคิดว่ามันมีความชัดเจนมากขึ้นในการใช้โดยตรง moveCametaTo (latLng) เป็นเหมือนไฟล์ใน java คุณสามารถผ่านเส้นทางเช่นสตริงหรือคลาสเส้นทาง
Tlaloc-ES

1

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

การมีวิธีการหนึ่งเรียกอีกวิธีหนึ่งก็เป็นสิ่งสำคัญเช่นกันเนื่องจากคุณไม่ต้องการให้มีการทำซ้ำรหัสในวิธีการเหล่านั้น เมื่อคุณทำเสร็จแล้วให้เลือกวิธีหนึ่งเพื่อให้เป็นวิธีที่ใช้งานได้และให้วิธีอื่นเรียกว่า (โดยตรงหรือโดยอ้อม)


1

หากคุณคำนึงถึงการใช้วิธีการต่าง ๆ มันเป็นคุณสมบัติที่ใช้วิธีการมากเกินไปที่จะดี

แต่มีไม่ได้ขจัดความรับผิดชอบของการรู้สิ่งที่เป็น LatLng LatLng latLng = new LatLng(latitude, longitude)เพราะคุณกำลังเริ่มต้น นี่คือการพึ่งพาLatLngทั้งหมด (เพื่อเข้าใจว่าทำไม Initializing ปัญหาพึ่งพาคุณสามารถตรวจสอบการพึ่งพาการฉีด ) LatLngการสร้างวิธีการมากเกินไปเพียงแค่ช่วยให้ลูกค้าที่ไม่ได้ดูแล ถ้าคุณหมายถึงสิ่งนี้มันก็ดี แต่ฉันไม่คิดว่ามันเป็นแนวทาง มันเป็นเพียงวิธีการบริการมากมายสำหรับลูกค้า

ดังนั้นมีสองตัวเลือกในการออกแบบสถาปัตยกรรมของคุณ:

  1. สร้างวิธีการโอเวอร์โหลดจำนวนมากและมอบให้กับลูกค้า
  2. สร้างวิธีโอเวอร์โหลดที่ต้องการพารามิเตอร์เป็นอินเทอร์เฟซหรือคลาสคอนกรีต

ฉันวิ่งหนีให้ได้มากที่สุดจากการสร้างวิธีการที่ต้องการประเภทดั้งเดิมเป็นพารามิเตอร์ (ตัวเลือก 1) เพราะหากธุรกิจของคุณเปลี่ยนแปลงหลายครั้งและคุณจำเป็นต้องเล่นพารามิเตอร์วิธีการมันเป็นเรื่องยากที่จะเปลี่ยนและใช้ฟังก์ชั่นผู้โทรทั้งหมด

แทนที่จะใช้สิ่งนี้ให้ใช้อินเตอร์เฟส (Dependency Injection) หากคุณคิดว่ามีค่าใช้จ่ายและใช้เวลามากขึ้นให้ใช้คลาสและจัดเตรียมวิธีการส่วนขยาย mapper (ตัวเลือก 2)

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