Skip to content

Instantly share code, notes, and snippets.

@amorfati0310
Forked from haeguri/data.json
Created November 25, 2018 09:02
Show Gist options
  • Save amorfati0310/182caaed894ed179500cd97e117afcff to your computer and use it in GitHub Desktop.
Save amorfati0310/182caaed894ed179500cd97e117afcff to your computer and use it in GitHub Desktop.
[ codespitz-75 ] 1강 과제
{
"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%"]
]
}
<!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