Repository navigation
Design Document
Yoo Jae Beom edited this page Jun 9, 2016
·
47 revisions
- 1 ๋งฅ๋ถ, 1 ๊ธฐ๊ฐ๋ฐ์ดํธ, 2 ์ํผ์ค๋ก ๊ฐ๋ฐ ํ๊ฒฝ์ ์ฐจ์ด๊ฐ ์ฌํจ
- ๊ฐ๋ฐ ํ๊ฒฝ์ ์ต๋ํ ๋ง์ถ๊ธฐ ์ํด jetbrain์ IntelliJ๋ฅผ ์ด์ฉํ๊ณ Build tool๋ก gradle์ ์ ํ.
- Gradle
LCS ์๊ณ ๋ฆฌ์ฆ์ ์๋์ ๊ฐ์ ํด๋์ค ์ธํฐํ์ด์ค ํ์ ํธ์ถํ๋๋ก ์ค๊ณํ์๋ค.
public class LCS<T extends Comparable<T>> implements Diff.Algorithm<T> {
@Override
public List<Pair<Integer>> diff(List<T> l, List<T> r) { ... }
...
}LCS ํด๋์ค์ diff ๋ฉ์๋๋ List 2๊ฐ๋ฅผ ๋ฐ์ ๋น๊ตํ์ฌ ๊ณตํต๋๋ ์์ด์ ๋ฆฌ์คํธ ์ธ๋ฑ์ค ์์ ๋ฐํํ๋ ๋ฉ์๋์ด๋ค. diff ๋ฉ์๋์ ๊ตฌํ์ ๋ฆฌ์คํธ์ ์์๊ฐ ๊ณตํต๋๋ ์์์ธ์ง ํ์ธํ ์ ์๋ ๋น๊ต ๋ฉ์ปค๋์ฆ์ด ํ์ํ๋ค. ์ด๋ฅผ ์ํด Comparable์ ์๋ธํ์ ๋ง LCS ํด๋์ค๋ฅผ ์์ฑํ ์ ์๋๋ก ์ ์ฝ์ ๊ฑธ์ด๋์๋ค.
๋ฐ๋ผ์ ์ดํ์ ํ ์คํธ๋ฅผ String๋ณด๋ค ๋ณต์กํ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋๋ผ๋ compareTo ๋ฉ์๋๋ง ๊ตฌํํ๋ฉด LCS ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์๋๋ diff ๋ฉ์๋์ ๋ฐํ๊ฐ์ ๋ํ ์ค๋ช ์ด๋ค.
๊ฐ Pair<Integer>๋ LCS ์๊ณ ๋ฆฌ์ฆ ํ์์ ๋งค์นญ๋๋ ์ธ๋ฑ์ค ์์ด๋ค.
์๋ฅผ ๋ค์ด List<T> L, R์ด T=Character ์ผ ๋ ์๋ ์ฒ๋ผ ๋ค์ด์๋ค๊ณ ๊ฐ์ ํ๋ฉด
L: ['a', 'b', 'c']
R: ['a', 'c', 'd']
์ด๋ฉด LCS๋ ['a', 'c'] ์ด๋ค.
LCS์ ์ฒซ ์์์ธ 'a'์ ๋ํด์๋ Pair<Integer>๋ (0, 0) ์ด๋ค.
> L์์๋ index 0 ์์น์ 'a'๊ฐ ์๊ณ , R์์๋ index 0 ์์น์ 'a'๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
LCS์ ๋๋ฒ์งธ ์์์ธ 'c'์ ๋ํด์๋ Pair<Integer>๋ (2, 1) ์ด๋ค.
> L์์๋ index 2 ์์น์ 'c'๊ฐ ์๊ณ , R์์๋ index 1 ์์น์ 'c'๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋ณด์ด๋ ๋ฐ์ ๊ฐ์ด Controller๊ณผ EditPanel์ ๊ฐ๊ฐ Merge์ JavaFX์ ์ข ์์ ์ด์ง๋ง ๊ฐ๊ฐ์ Model. View ๋ถ๋ถ์ด Controller ๋ถ๋ถ์ ์ข ์์ ์ด์ง๋ ์์.
- ํ ํด๋์ค๋ ํ๋์ ์ฑ ์๋ง ๊ฐ์ ธ์ผ ํ๋ค.
- ์ด์ ๋ํ ์ค๋ช ์ ์๋ Designed to be testable by unit-test tools ๋ถ๋ถ์ ์ค๋ช ๊ณผ ์ผ๋งฅ์ํตํ๋ฏ๋ก ์๋ตํ๊ฒ ๋ค.
- ์ํํธ์จ์ด ์์๋ ํ์ฅ์๋ ์ด๋ ค ์์ผ๋ ๋ณ๊ฒฝ์๋ ๋ซํ์์ด์ผ ํ๋ค.
package SimpleMerge.util;
public class Pair<T> {
public final T first, second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?> pair = (Pair<?>) o;
if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
return second != null ? second.equals(pair.second) : pair.second == null;
}
@Override
public int hashCode() {
int result = first != null ? first.hashCode() : 0;
result = 31 * result + (second != null ? second.hashCode() : 0);
return result;
}
}
- Generic์ผ๋ก ๊ตฌํ๋ Pair๋ ๋ชจ๋์ ๊ธฐ๋ฅ ํ์ฅ์ด๋ ๋ณ๊ฒฝ์ ๋ค๋ฅธ ํด๋์ค์ ๋ฌด๊ดํ๊ฒ ์งํ ํ ์ ์๋ค.
- ํ๋ก๊ทธ๋จ์ ๊ฐ์ฒด๋ ํ๋ก๊ทธ๋จ์ ์ ํ์ฑ์ ๊นจํธ๋ฆฌ์ง ์์ผ๋ฉด์ ํ์ ํ์ ์ ์ธ์คํด์ค๋ฅผ ๋ฐ๊ฟ ์ ์์ด์ผ ํ๋ค.
package SimpleMerge.diff;
import SimpleMerge.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class Diff<T extends Comparable<T>> {
interface Algorithm<T extends Comparable<T>> {
List<Pair<Integer>> diff(List<T> l, List<T> r);
}
private Algorithm<T> algorithm;
private List<Pair<Integer>> commonLineIndexes;
private Pair<List<Block>> diffBlocksPair;
private List<T> list1, list2;
public Diff() {
this.algorithm = getDefaultAlgorithm();
}
public Diff(List<T> list1, List<T> list2) {
this.algorithm = getDefaultAlgorithm();
this.compare(list1, list2);
}
private Algorithm<T> getDefaultAlgorithm() {
return new LCS<T>();
}
public void setAlgorithm(Algorithm<T> algorithm) {
this.algorithm = algorithm;
}
public List<Pair<Integer>> compare(List<T> list1, List<T> list2) {
this.list1 = list1;
this.list2 = list2;
commonLineIndexes = algorithm.diff(list1, list2);
diffBlocksPair = null;
return commonLineIndexes;
}
public Pair<List<Block>> getDiffBlocks() {
if (diffBlocksPair != null) {
return diffBlocksPair;
}
List<Block> blocks1 = new ArrayList<>(), blocks2 = new ArrayList<>();
int lastLineIndex1 = -1, lastLineIndex2 = -1;
for (Pair<Integer> pair : commonLineIndexes) {
if (lastLineIndex1 + 1 != pair.first || lastLineIndex2 + 1 != pair.second) {
blocks1.add(new Block(lastLineIndex1 + 1, pair.first));
blocks2.add(new Block(lastLineIndex2 + 1, pair.second));
}
lastLineIndex1 = pair.first;
lastLineIndex2 = pair.second;
}
if (lastLineIndex1 + 1 != list1.size() || lastLineIndex2 + 1 != list2.size()) {
blocks1.add(new Block(lastLineIndex1 + 1, list1.size()));
blocks2.add(new Block(lastLineIndex2 + 1, list2.size()));
}
diffBlocksPair = new Pair<>(blocks1, blocks2);
return diffBlocksPair;
}
}
- Diff๋ ๋ณด์ด๋ ๋ฐ์ ๊ฐ์ด Algorithm์ ๊ตฌํํ๊ณ ์๋ค. ์ด Algorithm ๋ถ๋ถ์ Algorithm์ implement ์ค์ธ LCS๋ก ๊ต์ฒด ํ์ฌ๋ ํ๋ก๊ทธ๋จ์ ์ ํ์ฑ์ด ์ ์ง๋๋ค.
- ํน์ ํด๋ผ์ด์ธํธ๋ฅผ ์ํ ์ธํฐํ์ด์ค ์ฌ๋ฌ ๊ฐ๊ฐ ๋ฒ์ฉ ์ธํฐํ์ด์ค ํ๋๋ณด๋ค ๋ซ๋ค.
- ์ ์ฅ ๋ฐ ๋ถ๋ฌ์ค๊ธฐ ๋ถ๋ถ์ ํจ์๋ฅผ ๋งก๋ EditPanelEventListener์ FileChooser์ ์ด์ฉํ๋ ํจ์๋ฅผ ๋งก๋ FileSelector๋ฅผ ๋ถ๋ฆฌ.
- ํ๋ก๊ทธ๋๋จธ๋ ์ถ์ํ์ ์์กดํด์ผ์ง ๊ตฌ์ฒดํ์ ์์กดํ๋ฉด ์๋๋ค.
- ๋ณธ ์ฝ๋๋ Class๊ฐ์ ์์์ด ๋ฐ์ํ์ง ์๋๋ค.
- ๋ณธ ์ฝ๋๋ Interface-Class๊ฐ ์์์ ์ด์ฉํ์ฌ View to Controller, Model to Controller ๋ฐฉํฅ์ ์์กด์ฑ์ ์ ๊ฑฐํ์๋ค.
- ์์ธํ ์์๋ ์๋จ์ MVC ์ค๋ช ๊ณผ ์ผ๋งฅ์ํตํ๋ฏ๋ก ์๋ตํ๊ฒ ๋ค.
- Mock์ด ํ ์คํธ๋ฅผ ํ ์ ์๋๋ก ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ๋ ๊ธฐ๋ฅ๋ค์ด ์๋ก ์์กด์ ์ด์ง ์๋๋ก Interface๋ก ๋ถ๋ฆฌ.
- Merger, LCS ๋ฑ MVC์์ ๋ชจ๋ธ์ ์์กดํ๋ ๊ตฌ์ฒด ํด๋์ค๊ฐ ์์ด ๋ณ๋์ Mocking ์์ด๋ ์ ๋ ํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋ค.
- MVC์์ Controller์ ํด๋นํ๋ EditPanel์ ์์กดํ๋ ์ปดํฌ๋ํธ๋ฅผ ์ธํฐํ์ด์ค(FileSelector)์ ์์กดํ๋๋ก ๋ง๋ค์ด Mockingํ์ฌ ํ ์คํธ๋๋๋ก ํ์๋ค.