結對第二次作業——頂會熱詞統計的實作
這個作業屬于哪個課程 | 2021春軟體工程實踐 | W班 (福州大學) |
---|---|
這個作業要求在哪裡 | |
結對學号 | 221801304&221801331 |
這個作業的目标 | 實作頂會熱詞統計的相關功能 |
其他參考文獻 | 無 |
git倉庫連結和代碼規範連結
git倉庫
代碼規範
補充部分前端代碼規範:
JS、CSS、HTML檔案命名
js、css、html的命名均采用小寫命名方式(templates下的html除外)
正例:detail.css、echarts.js、table.html
反例:Echarts.js、Detail.css
HTML類型聲明
使用HTML5的文檔類型申明,不使用XHTML或HTML4
正例:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta charset="UTF-8" />
<title>Page title</title>
</head>
<body>
<img src="images/company-logo.png" alt="Company" />
</body>
</html>
縮進
嵌套的節點應該縮進,并且同層節點縮進需一緻。
反例:<div> <p>111</p> <span>33</span> </div>
<div> <p>fa</p> <span>33</span> </div>
- CSS内部命名應該有意義
.conceal{ border:none; }
- 每個選擇器及屬性獨占一行
.btn{ width: 100px; height: 30px; }
多使用相對寬度,少用絕對寬度
這樣的目的主要是更容易适配不同浏覽器及螢幕。
項目位址
click here
PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
Planning | 計劃 | ||
• Estimate | • 估計這個任務需要多少時間 | 7day | 8day |
Development | 開發 | ||
• Analysis | • 需求分析 | 30 | |
• Dicussing & Design Spec | • 讨論交流 & 設計文檔 | 40 | |
• Design Review | • 設計複審 | 20 | 10 |
• Learning | • 學習新知識 | 60 | 80 |
• Coding Standard | • 代碼規範 | ||
• Coding | • 具體編碼 | 2500 | 3000 |
• Code Review | • 代碼複審 | ||
• Test | • 測試 | ||
Reporting | 報告 | ||
• Test Repor | • 測試報告 | ||
• Size Measurement | • 計算工作量 | ||
• Postmortem & Improvement Of The Prototype | • 事後總結, 并提出過程改進計劃 | ||
合計 | 2820 | 3310 |
成品展示
首頁
由頭部和側邊導航欄和主體三部分,主題采用輪播圖進行網站的推銷介紹(笑)。
可以在頭部搜尋框快速搜尋,根據标題模糊查詢,得到查詢結果的清單。 每個條目顯示标題、摘要、關鍵詞、會議、時間的資訊,點選詳情後可以觀看更詳細的内容。 詳情頁内的關鍵詞裡每個關鍵詞都可以點選,點選後可以跳轉到包含該關鍵詞的論文清單。 另外,在論文清單和詳情頁都可以删除該論文。進階搜尋頁
點選側邊欄的進階搜尋可以到進階搜尋頁面,可以進行标題、摘要、關鍵詞的模糊或精确查詢,還可以標明時間區間和會議,預設是2000-2020和三大會議都查詢(如果把三個會議都取消掉再查詢,會彈出提示資訊不讓你查詢)
順帶一提,這個分頁是可以用的,是真的分頁。熱詞統計頁
點選側邊欄的熱詞統計後,可以顯示熱詞top10,并且可以選擇檢視某個會議、某個年份區間的熱詞top10。
熱詞top10下面還有對應上面top10的詞雲,點選某個關鍵詞詞雲還可以跳轉到對應的論文清單。 點選柱狀圖中某個柱形,還可以檢視對應的這個熱詞的熱度走向圖,并且可以選擇檢視不同會議的走向。熱詞圖譜頁
點選側邊欄的熱詞圖譜可以到這個頁面,展示的是所有會議的2000到2020期間的所有熱詞熱度還有詞雲,點選這裡的詞雲依然可以跳轉到對應搜尋的論文清單。
結對讨論過程描述
有了第一次結對作業的經驗,加上第二次結對作業開始時我們已經返校,面對面交流友善了許多,是以第二次結對作業的準備工作還是比較迅速的。
開始讨論:由于在同一個宿舍,是以讨論比較友善。第二次結對作業釋出後,我們首先根據作業要求,把每一條需求映射到前端、後端,分别需要實作什麼進行了分析,并且生成了下面的文檔。
雖然一個人寫前端一個人寫後端,但是經常寫着寫着就跑去對方的電腦面前,看看對方正在寫什麼,并且提出自己的意見,通過不斷的交換意見,修改代碼,達成意見上的一緻。
遇到問題:在編碼的過程中,遇到的最大的問題是資料庫CRUD的效率問題,把爬取下來的資料映射完轉換後,插入過程不盡如人意,跑了一晚上居然還沒插入完成(???),并且到後面越來越慢,從一開始的一秒n條到最後一分鐘一條。
解決問題:後來,通過不斷地測試和搜尋引擎的資料查找與讨論後,發現問題在于:插入關鍵詞資訊之前使用了select(*)語句判斷關鍵詞是否存在,導緻每插入一條論文資料,就需要執行十多次該語句,在論文數量逐漸增大之後,該語句效率也越來越低,導入論文導入時間迅速增加。于是我們重構了資料庫,将論文和關鍵詞的對應關系由多對多改為一對多,将三張表改為了兩張表,雖然會有一些資料備援,但是大幅提升了性能,論文導入時間也縮短到了2分鐘。
遇到問題:在模糊查詢的過程中,由于需要連表,在本地進行一次查詢時間需要30s(當然也有電腦卡的原因),使用者體驗很差。
解決問題:将需要連表和模糊查詢的字段增加了索引,讓本地運作所需時間減少到了1s内
遇到問題:寫前端的時候,樣式問題困擾了許久,常常猶豫不決,有時寫完後發現不好看或者不合理,重寫樣式。加上第一次使用layui美化界面,不熟悉效果與用法,花了比較長的時間。
解決問題:不斷與隊友進行讨論,探讨頁面布局與樣式是否合理、美觀,設計好一個部分就commit一次,邀請隊友一起看效果,作出修改。研究layui官方文檔,通過不斷地測試樣式,調整樣式,把頁面做的更加美觀,同時也更加熟練的使用layui。
從需求分析開始到最後撰寫部落格,我們兩個人都沒有停止過讨論,我覺得這才是結對作業真正的意義所在,有交流才有改善,有交流才能解決問題。
下面附帶兩張讨論時的照片,讨論都是面對面交流。
設計實作過程
項目技術
本次項目前後端不分離,使用springboot開發。前端使用了thymeleaf模闆引擎進行前後端的資料庫互動,并使用了Layui美化了樣式
設計思路
- 資料庫
本次作業的資料主要有三部分,論文資訊、關鍵詞資訊、關鍵詞與論文之間的對應關系
我們将論文與關鍵詞之間設計成1對多的關系進行建表
- 子產品設計
主要将功能子產品分為兩個部分:論文管理和關鍵詞統計
論文的搜尋支援多條件模糊查詢;
關鍵詞統計子產品中包括了關鍵詞圖譜和top10排行;
實作過程
- 前端:使用thymeleaf做前後端資料傳遞,通過Layui美化樣式
前端項目結構圖
- 後端:使用java語言,通過SSM架構進行開發
後端項目結構圖
功能結構圖
代碼說明
論文進階檢索
<select id="selectPapersByMap" parameterType="map" resultMap="Paper">
SELECT p.pid,title,abst,p.conference,p.publicationYear,link,
keyword
FROM paper AS p
LEFT JOIN keyword AS k ON p.pid=k.pid
<where>
<!--精确查詢-->
<if test="etitle !=null and etitle !='' ">AND title=#{etitle}</if>
<if test="eabst !=NULL and eabst !='' ">AND abst=#{eabst}</if>
<if test="econference !=NULL and econference !=''">AND p.conference=#{econference}</if>
<if test="ekeyword !=NULL and ekeyword !=''">AND k.keyword=#{ekeyword}</if>
<!--模糊查詢-->
<if test="vtitle !=NULL and vtitle!=''">AND title LIKE '%${vtitle}%'</if>
<if test="vabst !=NULL and vabst !=''">AND abst LIKE '%${vabst}%'</if>
<if test="vkeyword !=NULL and vkeyword !=''">AND keyword LIKE '%${vkeyword}%'</if>
<!--年份查詢-->
<if test="publicationYear !=NULL and publicationYear !=''">AND p.publicationYear=#{publicationYear}</if>
<if test="beginYear !=NULL and beginYear !=''">AND p.publicationYear BETWEEN #{beginYear} AND #{endYear}</if>
<if test="link !=NULL and link !=''">AND link=#{link}</if>
<if test="conference !=NULL and conference !=''">
AND p.conference IN (1,
<if test="CVPR !=NULL and CVPR !=''">"CVPR",</if>
<if test="ECCV !=NULL and ECCV !=''">"ECCV",</if>
<if test="CVPR !=NULL and CVPR !=''">"CVPR",</if>
2)
</if>
</where>
</select>
使用mybatis實作dao層接口,通過将查詢參數傳入map進行查詢,可支援任意數量條件、模糊或精确查詢(不過使用map好像不太規範,下次封裝一個DO類來代替map)
論文展示(分頁)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageHelper
{
private List<String> pidList; //論文id清單
private int totalNum; //總條數
private int paperNum; //單頁面頁數
private int currentPage; //目前頁面
private int totalPage; //總頁數
/**
* 構造方法
* @param pidList
* @param paperNum
*/
public PageHelper(List<String> pidList, int paperNum)
{
this.pidList = pidList;
this.paperNum = paperNum;
this.totalNum=pidList.size();
this.currentPage=0;
this.totalPage=(totalNum%paperNum)==0?(totalNum/paperNum):(totalNum/paperNum+1);
}
/**
* 根據索引獲得清單
* @param start
* @param end
* @return
*/
public List<String> getListByIndex(int start,int end)
{
if(start>=totalNum || end<=0)
{
return new LinkedList<>();
}
if(end>=totalNum)
{
end=totalNum;
}
return pidList.subList(start,end);
}
/**
* 擷取指定頁号的内容
* @return
*/
public List<String> getPageByNum(int pageNum)
{
currentPage=pageNum;
return getListByIndex((pageNum-1)*paperNum,pageNum*paperNum);
}
/**
* 獲得上一頁的内容
* @return
*/
public List<String> getPrePage()
{
return getListByIndex((currentPage-1)*paperNum,currentPage--*paperNum);
}
/**
* 獲得下一頁的内容
* @return
*/
public List<String> getNextPage()
{
return getListByIndex((currentPage-1)*paperNum,currentPage++*paperNum);
}
封裝了一個PageHelper來幫助實作分頁,論文檢索時,将查詢結果的id清單存入List,進行分批讀取;
類裡封裝了一些方法進行讀取和周遊
關鍵詞圖譜
$(document).ready(function()
{
//根據條件請求資料
$.post('/getTop10Keywords/',{beginYear:2000,
endYear:2020,conference:''},function(data) {
data = JSON.parse(data);
//加載詞雲
CloudLoad(data);
});
})
function CloudLoad(data)
{
array.splice(0,array.length);
for(var i=0;i<data.x.length;i++)
{
var obj=new Object();
obj.text = data.x[i];
obj.weight = data.y[i]/100;
obj.link = "/getPapersByKeyword/"+data.x[i]; //為每個關鍵詞設定連結
array.push(obj);
}
//加載詞雲
$("#main").empty();
$("#main").jQCloud(array, { //設定參數
removeOverflowing: false,
shape: "elliptic",
width: 500,
height: 300
});
}
通過ajax異步請求後端資料,利用jQCloud元件進行關鍵詞圖譜的渲染
熱詞統計
function BarLoad(beginYear,endYear,conference)
{
bar.showLoading();
//根據篩選條件擷取後端資料
$.post('/getTop10Keywords/',{beginYear:beginYear,
endYear:endYear,conference:conference},function(data)
{
bar.hideLoading();
data=JSON.parse(data);
//加載詞雲
CloudLoad(data);
bar.setOption
({
title: {
text: beginYear==endYear?beginYear:(beginYear+'~'+endYear)+'年'+conference+'熱詞TOP10'
},
xAxis: {
data: data.x
},
series: [
{
type: 'bar',
data: data.y
}]
});
});
}
通過ajax異步請求後端資料,利用Echarts元件進行熱詞統計圖表的渲染
心路曆程和收獲
ZCX:這次作業是一次全新的體驗,我還是第一次對上十萬的資料進行處理。在導入論文以及進行查詢的過程中,經曆了一次次看着頁面轉圈圈的痛苦,第一次深切地體會到“性能”兩個字意味着什麼。在不斷debug、不斷修改的過程中,慢慢試着去關注性能,試着去深入代碼底層,進行調優。當論文導入時間從40分鐘改進到2分鐘的時候,真的有一種某名的快感。希望自己在未來的開發和編碼過程中,能夠不僅僅滿足于解決問題,而是追求更快、更優的解決方案。
WKJ:這是第一次寫一個項目的前端,以往都隻是手敲html、css、js,這次是比較規範的寫前端,各個方面都感覺挺新的,也是第一次接觸到layui和thymeleaf。雖然是第一次,但是通過不斷檢視示例,檢視官方文檔,再實踐應用,還是收獲頗豐的。一邊寫一邊看一邊修改,把一個空的界面變成有東西的界面,再變成美觀的界面,還是挺有成就感的。同時也體會到結對程式設計的快樂,通過跟隊友的讨論與交流,自身實力也得到了提高。
評價結對隊友
ZCX:這是和KJ的第二次結對合作,這一次的合作從線上轉為了線下,雙方的交流更多,也更友善了。因為在同一個宿舍,有時在睡覺前突然想到一個好點子,便會直接轉過頭來和對方分享讨論,大家都在這樣的交流讨論過程中開闊了思維,試着從多種角度思考問題。
KJ是一個非常有耐心、非常負責的隊友,能夠把每一項任務都完成到最好,和他合作效率很高。
WKJ:第二次結對合作,跟第一次相比,還是有不同的收獲的,首先從線上變成了線下,兩個人的交流變得更多了,而且因為第二次結對合作量比較大,合作交流顯得更為重要。在宿舍裡,常常代碼打着打着,就轉頭開始讨論,交換想法,在這種模式下,可以及時發現分歧并且解決。
CX是一個效率高、樂于助人的隊友,時常能提出很好的點子,跟他合作結對程式設計又充實又得到了成長,吸取了經驗。