รูปแบบการต่อต้านที่เลวร้ายที่สุดที่คุณเจอ [ปิด]


9

อะไรคือรูปแบบการต่อต้านที่เลวร้ายที่สุดที่คุณเคยประสบมาในฐานะโปรแกรมเมอร์

ฉันส่วนใหญ่มีส่วนร่วมในจาวาแม้ว่ามันอาจจะเป็นอิสระจากภาษา

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

คำตอบ:


38

รหัสออกความเห็น บล็อกของมันอาจจะหลายร้อยบรรทัด ทฤษฎีนี้เฮ้มันถูกคอมเม้นท์มันไม่ได้ทำอันตรายใด ๆ และบางทีเราอาจต้องการมันในอนาคต


7
อย่างน้อยคุณก็สามารถลบได้อย่างปลอดภัย ไม่เหมือนใครบางคนที่ฉันเคยทำงานด้วยซึ่งมักจะเปลี่ยนชื่อกระบวนงานและปล่อยให้รหัสตายตัวสามารถเข้าถึงได้ Blech
Jay

@Cyrena คุณทำงานกับ Eric ด้วยหรือไม่!?
CaffGeek

ฉันมีรหัสมากมายเมื่อใช้ #ifdef COMMENT เพื่อล็อกสิ่งต่าง ๆ ทำงานได้ดีจนกระทั่งมีคนนิยาม COMMENT
Michael Kohne

9
นี่เป็นอีกกรณีหนึ่งที่การใช้การควบคุมเวอร์ชันได้ผลตอบแทน คุณสามารถลบรหัสได้โดยไม่ต้องถามว่าคุณต้องการรหัสในอนาคตหรือไม่เพราะสามารถเรียกคืนได้อีกครั้งด้วยการกดแป้นบางครั้ง
Jason B

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

19

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

นี่เป็นที่แพร่หลายโดยเฉพาะในบางฟังก์ชั่นและรหัสการทดสอบ API จากปลายยุค 90: กรณีทดสอบที่เหมือนกันหลายร้อยตัว (หรือหลายพัน) ซึ่งสามารถแบ่งออกเป็นฟังก์ชั่นบางอย่างที่ใช้พารามิเตอร์ 3 หรือ 4 - หรือดียิ่งขึ้น สิ่งที่ขับเคลื่อนด้วยข้อมูล งานแรกของฉันจากวิทยาลัยคือการเขียนใหม่และการคัดลอกพาสต้าใหม่หลายพันบรรทัดซึ่งใช้วิธีการคัดค้าน ตามเวลาที่ฉันทำไฟล์ทดสอบมีขนาดน้อยกว่าหนึ่งในสิบของขนาดดั้งเดิมและสามารถบำรุงรักษาได้มากกว่า (และสามารถอ่านได้!)


16

ฉันคิดว่าฉันสามารถเขียนเยอะแยะเกี่ยวกับPattern Maniaและโซลูชันที่สามารถแก้ไขได้โดยใช้ความพยายามน้อยลง แต่ฉันอยากจะชี้ไปที่บทความที่ดีที่ฉันได้อ่านเมื่อเร็ว ๆ นี้พร้อมตัวอย่างที่ยอดเยี่ยมของวิธีแก้ปัญหาที่ง่าย ๆ .

อย่างไร (ไม่) ในการเขียน Factorial ใน Java หรือดังนั้นเราจึงใส่โรงงานเข้าไปในอัลกอริทึมของคุณ


3
! น่ากลัว FactorialWebService ตอนนี้อยู่ที่ไหน : P
FrustratedWithFormsDesigner

1
ฉันเรียกมันว่า Pattern Fever ... ทุกคนได้มาถึงจุดหนึ่งในอาชีพการงานของพวกเขา ที่ดีกว่าในหมู่พวกเราเติบโตเกินกว่าที่มัน ฉันได้สัมภาษณ์ที่ชายคนนั้นถามฉันเมื่อฉันควรคิดถึงรูปแบบ ฉันบอกเขาว่าฉันปล่อยให้พวกเขาพัฒนาเป็นระบบ เขากล่าวว่า "ไม่คุณควรใช้รูปแบบตั้งแต่เริ่มต้น"
Michael Brown

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

รูปแบบเป็นสิ่งประดิษฐ์ของการออกแบบที่ดี - ควรได้รับการปฏิบัติเช่นนี้ ฉันชอบที่จะอธิบายพวกเขาเป็นคำจำกัดความมากกว่าการแก้ปัญหา มีประโยชน์เมื่อสื่อสาร แต่ไม่จำเป็นต้องออกแบบ
Michael K

ขอบคุณมากสำหรับการอ่านที่ดี
Syg


14

ภูมิภาค

ใน C # คุณสามารถกำหนดขอบเขตของรหัสที่สามารถยุบใน IDE ได้ดังนั้นจึงซ่อนอยู่เว้นแต่คุณต้องการจัดการกับรหัสนั้น ฉันได้รับใน (ในขณะนี้) โครงการที่ภูมิภาคครอบคลุมหลายร้อยบรรทัด (หวังว่าฉันพูดเกินจริง) และมีหลายภูมิภาคในฟังก์ชั่นบรรทัดพัน (อีกครั้งฉันหวังว่าฉันถูกล้อเล่น)

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

ภูมิภาคสนับสนุนให้นักพัฒนา "ซ่อน" อึของพวกเขาในสายตาธรรมดา


15
+1 สำหรับภูมิภาคสนับสนุนให้นักพัฒนา "ซ่อน" อึของพวกเขาในสายตาธรรมดา อย่างไรก็ตามเมื่อใช้อย่างถูกต้องฉันพบว่าภูมิภาคช่วยในการจัดกลุ่มรหัสเข้าด้วยกันอย่างมีเหตุผลและหาได้ง่ายในภายหลัง
Darren Young

นี่เป็นปัญหาของตัวแก้ไขการพับ ฉันเคยทำสิ่งเดียวกันเมื่อฉันตั้งโปรแกรมครั้งสุดท้ายใน OCCAM
Michael Kohne

2
ฉันรักภูมิภาค ... แต่สำหรับองค์กรเท่านั้น ... ไม่ได้ซ่อนรหัสรีมดิจิทัล
IAbstract

3
+1 นั่นเป็นเหตุผลที่ใช้ภูมิภาคละเมิดกฎ StyleCop DoNotUseRegionsSA1124
Arseni Mourzenko

1
ฉันมีโครงการที่ทำงานกับเขตข้อมูลจำนวนมากใน SQL และรหัสที่ปรับปรุง / สร้างมันมีหลายบรรทัด พื้นที่#region SQL Updateทำให้พับได้ดังนั้นจึงจำเป็นต้องเลื่อนน้อยลง
JYelton


9

ไม่ใช่วิธีการบรรทุกเกินพิกัด:

// Do something
public int doSomething(Data d);

// Do same thing, but with some other data
public int doSomething2(SomeOtherData d);

แสดงให้เห็นชัดเจนว่าโปรแกรมเมอร์ไม่เข้าใจการทำงานหนักเกินไป


5

วนสลับลำดับ

http://en.wikipedia.org/wiki/Loop-switch_sequence

พวกเขาทำให้ฉันรำคาญไม่จบและแสดงให้เห็นว่า dev นั้นไม่มีประสบการณ์


Ah, เครื่องสถานะสิ้นสุด :)

ทำไมคุณต้องนำความทรงจำที่ถูกฝังเหล่านี้มาเล่า ฉันมีวันที่ดี
มาลาคี

5

ซอฟต์โค้ดคือเมื่อโปรแกรมเมอร์ออกนอกเส้นทางเพื่อหลีกเลี่ยงการเข้ารหัสและจบลงที่ด้านอื่น ๆ ของสเกล - การพึ่งพา "รหัสยาก"


4

รักษาสถานะในไคลเอนต์

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


คุณช่วยอธิบายรายละเอียดได้ไหม? Imho สำหรับเว็บแอปพลิเคชั่นมันใช้ได้ดีเมื่อมีเพียงสถานะเดียวเท่านั้นที่อยู่ในเบราว์เซอร์ (เช่นคุกกี้) และเซิร์ฟเวอร์คือ 'ไม่มีอะไรที่ใช้ร่วมกัน' หรือคุณหมายถึง 'สถานะ' ใน 'ฐานข้อมูลแอปพลิเคชัน'?
keppla

รัฐ: ในขณะที่ข้อมูลจริงที่จะดำเนินการ

OO คุณมีความเห็นอกเห็นใจที่ลึกที่สุดของฉัน
keppla

4

Checkins ขนาดใหญ่

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

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


1
การไม่ทำอะไรเลยไม่ใช่กรณีที่เลวร้ายที่สุดเสมอไป บางครั้งมันจะดีกว่าที่จะต้องมีการเขียนจากรอยขีดข่วนมากกว่าที่จะมีรหัสที่จะเขียน ...
มาลาคี

4

ขณะนี้ฉันทำงานกับรหัสเดิมและฉันชอบวิธีที่ coder ก่อนหน้าได้รับองค์ประกอบแรกของรายการ:

String result;
for(int i = 0; i < someList.size(); i++) {
    result = someList.get(i);
    break;
}

แต่สิ่งที่แย่ที่สุดที่ฉันเคยเห็นในรหัสนี้คือการกำหนดคลาสอินไลน์เพจ JSPs เขียน HTML, CSS และ Javascript ทั้งหมดโดยใช้ scriptlet และ out.println :-(


4

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

ความจริงที่ว่านี่เป็นนโยบายแผนกทำให้แย่ยิ่งกว่ากรณีของผู้พัฒนารายเดียวที่ดำเนินการในลักษณะนี้


3

ล็อคตัวอักษรสตริง

synchronized("one") { /* block one A*/ }

synchronized("one") { /* block one B*/ }

ชื่อชั้นยาวมาก (ใน JRE)

com.sun.java.swing.plaf.nimbus.
InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState

โครงสร้างการสืบทอดไม่ดี

com.sun.corba.se.internal.Interceptors.PIORB extends
com.sun.corba.se.internal.POA.POAORB extends
com.sun.corba.se.internal.iiop.ORB extends
com.sun.corba.se.impl.orb.ORBImpl extends
com.sun.corba.se.spi.orb.ORB extends
com.sun.corba.se.org.omg.CORBA.ORB extends 
org.omg.CORBA_2_3.ORB extends
org.omg.CORBA.ORB

ข้อยกเว้นซึ่งไม่ใช่

public interface FlavorException { }

การจัดการข้อผิดพลาดที่ไม่มีจุดหมายและเป็นความลับ

if (properties.size() > 10000)
   System.exit(0);

การสร้างวัตถุที่ไม่จำเป็น

Class clazz = new Integer(0).getClass();
int num = new Integer(text).intValue();

โยนข้อยกเว้นเพื่อวัตถุประสงค์อื่น

try {
    Integer i = null;
    Integer j = i.intValue();
} catch (NullPointerException e) {
    System.out.println("Entering "+e.getStackTrace()[0]);
}

ใช้วัตถุตัวอย่างสำหรับวิธีการคงที่

Thread.currentThread().sleep(100);

การซิงโครไนซ์บนเขตข้อมูลที่ไม่ใช่ครั้งสุดท้าย

synchronized(list) {
   list = new ArrayList();
}

สำเนาไม่มีค่าของสตริงคงที่

String s = new String("Hello world");

การโทรแบบไม่มีจุดหมายไปยัง String.toString ()

String s = "Hello";
String t = s.toString() + " World";

โทรไปที่ System.gc () เพื่อเพิ่มหน่วยความจำ

การตั้งค่าตัวแปรท้องถิ่นเป็นโมฆะเพื่อเพิ่มหน่วยความจำ

    // list is out of scope anyway.
    list = null;
}

การใช้ ++ i แทน i ++ สำหรับเหตุผลด้านประสิทธิภาพ (หรือการเพิ่มประสิทธิภาพไมโครไมโครอื่น ๆ )


สิ่งเหล่านี้ไม่จำเป็นต้องมีรูปแบบการต่อต้าน แต่การเขียนโค้ดไม่ดี
Gary Willoughby

@ แกรี่หรือรูปแบบการพัฒนาไม่ดีฉันเห็นซ้ำแล้วซ้ำอีก อาจไม่ได้อยู่ในคำจำกัดความที่เข้มงวดของรูปแบบการต่อต้าน
Peter Lawrey

1
@Peter: "Calls to System.gc () เพื่อเพิ่มหน่วยความจำ" ฉันได้เห็นโอกาสครั้งหนึ่งที่. NET จะระเบิดด้วยข้อยกเว้น OutOfMemory ยกเว้นว่า GC ถูกเรียกอย่างชัดเจน แน่นอนมันเป็นข้อยกเว้นมากกว่ากฎ
Coder


2

Iterator สำหรับหุ่น:

Iterator iCollection = collection.iterator();
for(int i = 0 ; i < collection.size() ; i++ ){
    if(collection.get(i) == something){
       iCollection.remove();
    }
 }

Singletono โรงงาน:

public class SomeObject{
   private SomeObject() {}
   public static SomeObject getInstance(){
       return new SomeObject();
   }
}

การพัฒนาที่ขับเคลื่อนด้วย if-else (เรียกอีกอย่างว่าหลักการเปิดปิด - เปิดเพื่อการปรับเปลี่ยนเพื่อความเข้าใจ):

if (sth1){
...  
}else if(sth2){
..
}
...
..
else if(sth1000000000000){
...
}

StringPattern (หรือที่เรียกว่า StringObject):

a) sendercode
if(sth1)
   str+="#a";
if(sth2)
   str+="#b";
...
if(sth1000)
   str+="#n";

b) receiver
   regexp testing if str contains #a, #b, ... #n

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

IMHO แต่ละรายการหาก / else สามารถแทนที่ด้วยการจับคู่อย่างง่ายหรือรูปแบบผู้เยี่ยมชม ในกรณีของสตริงเช่นคุณอาจมีไฟล์คุณสมบัติเช่น: someString1 = some.package.ObjectToHandleSomeString1
Marcin Michalski

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

exacly นั่นเป็นสาเหตุที่ทำให้เกิดความสับสน :) หากวิธีการนั้นถูกเรียกว่า create () หรือมันจะคืนค่าอินสแตนซ์เดียวกันทุกครั้งที่ทุกอย่างเรียบร้อยดี
Marcin Michalski

2

มันไม่ได้เป็นรูปแบบการเข้ารหัสมากนัก แต่เป็นรูปแบบพฤติกรรมมันค่อนข้างแย่แม้ว่า: การแก้ไขบางอย่างในโค้ด (สมมติว่าข้อกำหนดเปลี่ยนไป) จากนั้นทำการปรับแต่งการทดสอบหน่วยทั้งหมดจนกว่ารหัสจะผ่าน Tweaking หรือเพียงแค่เอารหัสทดสอบทั้งหมดออกจากวิธีการทดสอบ แต่ปล่อยให้วิธีนั้นมีอยู่

สิ่งนี้เชื่อมโยงกับรูปแบบทั่วไปที่มากขึ้นนั่นคือ รูปแบบของสิ่งที่ต้องทำนี่คือบรรทัดของรหัสที่เป็นตัวแทน:

int num = new Integer( stringParam ).parseInt( stringParam );

มันทำงานได้หลังจากทั้งหมด


2

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

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

  2. ใน MATLAB และ R การยืนยันว่าทุกอย่างเป็นเวกเตอร์ / เมทริกซ์แทนที่จะเป็นแบบดั้งเดิม

  3. ในขณะที่เราทุบตี MATLAB วิธีการเกี่ยวกับความจริงที่ว่ามันไม่มีจำนวนเต็มดังนั้นเมื่อคุณต้องการจำนวนเต็มคุณต้องใช้สองครั้ง

  4. ภาษาที่ใช้งานได้จริงซึ่งคุณต้องใช้การเรียกใช้ฟังก์ชันเพื่อเขียนลูป


1

มันจะเป็นการคัดลอก / วางอย่างแน่นอนฉันได้เห็นโค้ดที่ไม่ดีมากมายที่ต้องทำเพราะมันและการเข้ารหัสโคบาลและทุกอย่างที่เกิดขึ้นจากนั้น (คลาสพระเจ้าวิธีการขนาดใหญ่พิเศษอัลกอริธึมที่ไม่ดี ฯลฯ )

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


1

จาวาถั่วอเนกประสงค์ -

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

นอกจากนี้อย่าลืมคนรักด้วย

try{ 
   ... //many lines of likely dangerous operations
}
catch(Exception e){}

IMHO ข้อยกเว้นเหม็น พวกเขายากเกินไปที่จะทำให้ถูกต้องและเพิ่มความปลอดภัย
Coder

ไม่ว่าความคิดเห็นของคุณเกี่ยวกับความเหม็นของข้อยกเว้นคืออะไรการกลืนอย่างเงียบ ๆ ต้องทำให้เหม็นมากกว่า
Steve B.

1

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


1

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


เสียงชนิดเช่นอาศัยเซสชันและ ViewState ใน ASP.NET จะผ่าน gobs ของข้อมูลระหว่างหน้าซึ่งเศร้ามักจะต้อง ...
เวย์น Molina

1

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


0

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

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

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

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

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

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

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

หมายเหตุ: ฉันไม่ได้พูดว่ารูปแบบนี้ไม่ดีโดยเนื้อแท้ แต่ในตัวอย่างนี้ฉันพบว่ามันไม่จำเป็นเมื่อหลักการ OO พื้นฐานจะพอเพียง

ฉันไม่แน่ใจชื่อของรูปแบบการต่อต้านนี้เพราะนี่เป็นครั้งแรกที่ฉันเห็นอะไรแบบนี้ ชื่อที่ดีที่คุณคิดเกี่ยวกับรูปแบบนี้?


ฉันจะไม่เรียกปัญหานี้ว่าผ้าห่ม มันขึ้นอยู่กับจำนวนข้อมูลชั่วคราวที่ถูกจัดเก็บและสิ่งที่ทำกับมัน
GrandmasterB

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

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

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

0

รถเข็นก่อนม้า - อาคา YouMightNeedIt

ตัวอย่างเช่น:

  • การสร้างสคีมา RDMB ด้วยแนวคิดที่เป็นนามธรรมอ้างอิงโยง - ในสาระสำคัญคือคิวบ์ดาต้าที่เกินมาตรฐาน ... และจากนั้นคุณสมบัติการเขียนรอบ ๆ โมเดลที่ทำทุกอย่าง

นั่นจะเป็นพี่ชายฝาแฝดของ YAGNI ใช่ไหม?
Wayne Molina

0

IMO รูปแบบการต่อต้านที่แย่ที่สุดที่ฉันเคยเห็นคือ "เราไม่ต้องการรูปแบบของกลิ่นเหม็น" Anti-Pattern: ความคิดที่ว่ารูปแบบการออกแบบนั้นเสียเวลาและคุณสามารถเขียนโค้ดได้เร็วขึ้นโดยเพียงแค่ลอกมันเข้าด้วยกันและคัดลอก / วางได้ตามต้องการ

รางวัลชมเชยไปที่การมีรหัสที่โหลดวัตถุจากฐานข้อมูลโดยใช้รูปแบบ VB6 เก่าของ:

Foobar oFoo = new Foobar();
oFoo.FooID = 42;
if (oFoo.Load()) { 
    // do something with oFoo
}

ไม่ใช่รูปแบบการต่อต้าน แต่แสดงให้เห็นถึงการขาดการใช้ประโยชน์จากสถาปัตยกรรมที่เหมาะสมและการแยกข้อกังวล

นอกจากนี้สิ่งนี้:

// this name is misleading, we may not always want to stand in fire,
// we may want to stand in slime or voidzones or ice patches...
public Foobar StandInFire() { }

// why is this here???
public string BeatWithNerfBat(string whom) { }

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