-
-
Save amorfati0310/182caaed894ed179500cd97e117afcff to your computer and use it in GitHub Desktop.
[ codespitz-75 ] 1강 과제
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"title": "TIOBEIndex for June 2017", | |
"header": [ | |
"Jun-17", | |
"Jun-16", | |
"Change", | |
"Programming Language", | |
"Ratings", | |
"Change" | |
], | |
"items": [ | |
[1, 1, "", "Java", "14.49%", "-6.30%"], | |
[2, 2, "", "C", "6.85%", "-5.53%"], | |
[3, 3, "", "C++", "5.72%", "-0.48%"], | |
[4, 4, "", "Python", "4.33%", "0.43%"], | |
[5, 5, "", "C#", "3.53%", "-0.26%"], | |
[6, 9, "", "change", "Visual Basic .NET", "3.11%", "0.76%"], | |
[7, 7, "", "JavaScript", "3.03%", "0.44%"], | |
[8, 6, "change", "PHP", "2.77%", "-0.45%"], | |
[9, 8, "change", "Perl", "2.31%", "-0.09%"], | |
[10, 12, "change", "Assembly language", "2.25%", "0.13%"], | |
[11, 10, "change", "Ruby", "2.22%", "-0.11%"], | |
[12, 14, "change", "Swift", "2.21%", "0.38%"], | |
[13, 13, "", "Delphi/Object Pascal", "2.16%", "0.22%"], | |
[14, 16, "change", "R", "2.15%", "0.61%"], | |
[15, 48, "change", "Go", "2.04%", "1.83%"], | |
[16, 11, "change", "Visual Basic,2.01%", "-0.24%"], | |
[17, 17, "", "MATLAB", "2.00%", "0.55%"], | |
[18, 15, "change", "Objective-C", "1.96%", "0.25%"], | |
[19, 22, "change", "Scratch", "1.71%", "0.76%"], | |
[20, 18, "change", "PL/SQL", "1.57%", "0.22%"] | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>1번 과제</title> | |
</head> | |
<body> | |
<section id="data"></section> | |
<script> | |
// | |
// [ 과제 #1 ] | |
// Q. 실제 코드를 구현하고 실행하면 예외가 발생한다. 예외 지점을 찾고 수정하여 완성하라. | |
// | |
// [ 과제 #2 ] | |
// Q. 지금까지 전개한 객체협력모델에서는 여전히 문제가 남아있다. Info는 Data와 Renderer 사이에 교환을 위한 프로토콜인데, | |
// Renderer의 자식인 TableRenderer도 Info에 의존적인 상태다. 이를 개선하라. | |
// | |
const Data = class{ | |
async getData(){ | |
const json = await this._getData(); | |
return new Info(json); | |
} | |
async _getData(){ | |
throw '_getData must overrided'; | |
} | |
} | |
const JsonData = class extends Data{ | |
constructor(data){ | |
super(); | |
this._data = data; | |
} | |
async _getData(){ | |
if(typeof this._data === 'string') { | |
const response = await fetch(this._data); | |
return await response.json(); | |
} else return this._data; | |
} | |
} | |
const Renderer = class{ | |
async render(data) { | |
if(!(data instanceof Data)) throw 'invalid param'; | |
// [ 과제 #2 풀이 ] | |
// - title, header, items 데이터를 this._data에 저장. | |
// - TableRenderer에서 Info를 직접 참조하는 것을 없애고, 부모에 선언된 this._data만 참조하도록 변경 | |
const _info = await data.getData(); | |
this._data = { | |
caption: _info.title, | |
header: _info.header, | |
items: _info.items | |
} | |
this._render(); | |
} | |
async _render(){ | |
throw '_render must overrided'; | |
} | |
} | |
const TableRenderer = (_=>{ | |
const Private = Symbol(); | |
return class extends Renderer{ | |
constructor(parent){ | |
super(); | |
if(typeof parent !== 'string' || !parent) throw 'invalid param'; | |
this[Private] = {parent}; | |
} | |
async _render() { | |
const parent = document.querySelector(this[Private].parent); | |
if(!parent) throw 'invalid parent'; | |
parent.innerHTML = ""; | |
const table = document.createElement('table'); | |
const caption = document.createElement('caption'); | |
// _info.title => data.caption | |
caption.innerHTML = this._data.caption; | |
table.appendChild(caption); | |
table.appendChild( | |
// _info.header => _data.header | |
this._data.header.reduce( | |
(thead, data)=>(thead.appendChild(document.createElement('th')).innerHTML = data, thead), | |
document.createElement("thead")) | |
); | |
parent.appendChild( | |
// _info.items => _data.items | |
this._data.items.reduce( | |
(table, row)=>(table.appendChild( | |
row.reduce( | |
(tr, data)=>(tr.appendChild(document.createElement('td')).innerHTML = data, tr), | |
document.createElement('tr')) | |
), table), | |
table) | |
); | |
} | |
} | |
})(); | |
const Info = class{ | |
constructor(json){ | |
const {title, header, items} = json; | |
if(typeof title !== 'string' || !title) throw 'invalid title'; | |
if(!Array.isArray(header) || !header.length) throw 'invalid header'; | |
if(!Array.isArray(items) || !header.length) throw 'invalid items'; | |
items.forEach((row, idx)=>{ | |
// [ 과제 #1 풀이 ] | |
// - items 필드 검증 코드의 바깥에 try/catch 추가 | |
// - 로우 데이터가 더 많다면 pop 메서드로 여분의 로우 데이터를 제거 | |
// - 로우 데이터가 더 적다면 push 메서드로 빈 문자열 ''을 로우 데이터에 추가 | |
try{ | |
if(!Array.isArray(row) || row.length !== header.length) { | |
throw 'invalid items:' + idx; | |
} | |
}catch(eMsg){ | |
console.log(eMsg); | |
if(row.length > header.length){ | |
while(row.length !== header.length) row.pop(); | |
} | |
else if(row.length < header.length){ | |
while(row.length !== header.length) row.push(''); | |
} | |
} | |
}); | |
this._private = {title, header, items}; | |
} | |
get title(){return this._private.title;} | |
get header(){return this._private.header;} | |
get items(){return this._private.items;} | |
}; | |
const jsonData = new JsonData('data.json'); | |
const tableRenderer = new TableRenderer('#data') | |
tableRenderer.render(jsonData); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment