צמצמתי:טיפול ב-if מקונן לפי מצב
הכתורות הקצרות בתפוז כמעט מיאשות

אני מצמצם את השאלה והתמקדות ה-refactoring לקטע מתוך מחלקה אחת. זוהי מחלקה המטפלת בקלט מהמשתמש, ומתיחסת עליו בצורות שונות, לפי עיבודים קודמים ואירועים חיצוניים. יש לי למעשה if-ים מקוננים כדי להגיע למצב הנוכחי, למרות שזה לא נראה כך כי כל if נמצא במתודה נפרדת. נסיתי להשתמש ב State Pattern אבל נראה שזה הוסיף הרבה יותר קוד ממה שרציתי. עדיין יתכן שאם אתקן את חשיפת המצב לגורמים חיצוניים, אוכל לשנות את ההתנהגות "במכה אחת" בהתאם לאירוע החיצוני. (כרגע יש כמה שדות public שהכנסתי כי לא ידעתי באותו רגע איך לאפשר שינוי נקי בהתנהגות) יש מצב שמשנה את ההתנהגות לגמרי, ויש כזה שמשנה קצת את הקלט ומעביר אותו הלאה. אני לא יודע אם צריך להתיחס אליהם אחרת. המצב שמתחלף בעקבות אירועים חיצוניים ראוי לטיפול משלו, אבל לא אלאה עם זה כרגע. הנה החלק החשוב של הקוד. אחריו מודבקת המחלקה כולה, אם מישהו מרגיש צורך בפרטים. מתודות תלויות מצב הן: insertString, remove, replace ואלו שנקראות מתוכן.
public void replace(int offset, int length, String sub) { replacing = true; delegator.replace(offset, length, sub); } public void insertString(int offset, String addition) { replacing = false; TextFieldOutputFactory.TextFieldOutput output = factory.createOutput(delegator, new DefaultInsert(offset, addition)); insertString(offset, addition, output); autoFilledState = output.autoFilled(); } public void insertString(int offset, String addition, Output output) { String proposedValue = new StringBuilder(getText()).insert(offset, addition).toString(); matcher.match(proposedValue, output); } public void remove(int offset, int length) { removeMethodSelector(offset, length); replacing = false; } private void removeMethodSelector(int offset, int length) { if (replacing) { delegator.remove(offset, length); } else { removeDependOnState(offset, length); } } private void removeDependOnState(int offset, int length) { if (backspacing && autoFilledState) { offset--; length++; } TextFieldOutputFactory.TextFieldOutput output = factory.createOutput(delegator, new DefaultRemove(offset, length)); remove(offset, length, output); autoFilledState = output.autoFilled(); } public void remove(int offset, int length, Output output) { String proposedValue = new StringBuilder(getText()).delete(offset, offset + length).toString(); matcher.match(proposedValue, output); }
והמחלקה כולה:
public class AutoFillPlugin implements yon.ui.autofill.PluggablePlainDocument.Plugin { public void acceptDelegator(yon.ui.autofill.PluggablePlainDocument.Delegator delegator) { this.delegator = delegator; } public void replace(int offset, int length, String sub) { replacing = true; delegator.replace(offset, length, sub); } public void insertString(int offset, String addition) { replacing = false; TextFieldOutputFactory.TextFieldOutput output = factory.createOutput(delegator, new DefaultInsert(offset, addition)); insertString(offset, addition, output); autoFilledState = output.autoFilled(); } public void insertString(int offset, String addition, Output output) { String proposedValue = new StringBuilder(getText()).insert(offset, addition).toString(); matcher.match(proposedValue, output); } public void remove(int offset, int length) { removeMethodSelector(offset, length); replacing = false; } private void removeMethodSelector(int offset, int length) { if (replacing) { delegator.remove(offset, length); } else { removeDependOnState(offset, length); } } private void removeDependOnState(int offset, int length) { if (backspacing && autoFilledState) { offset--; length++; } TextFieldOutputFactory.TextFieldOutput output = factory.createOutput(delegator, new DefaultRemove(offset, length)); remove(offset, length, output); autoFilledState = output.autoFilled(); } &nb