軟工實踐結對作業二


結對第二次作業——頂會熱詞統計的實現

這個作業屬於哪個課程 2021春軟件工程實踐 | W班 (福州大學)
這個作業要求在哪里 結對第二次作業——頂會熱詞統計的實現
結對學號 221801304&221801331
這個作業的目標 實現頂會熱詞統計的相關功能
其他參考文獻

git倉庫鏈接和代碼規范鏈接

git倉庫
代碼規范
補充部分前端代碼規范:

  1. JS、CSS、HTML文件命名
    js、css、html的命名均采用小寫命名方式(templates下的html除外)
    正例:detail.css、echarts.js、table.html
    反例:Echarts.js、Detail.css

  2. 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>
  1. 縮進
    嵌套的節點應該縮進,並且同層節點縮進需一致。
    正例:
<div>
  <p>111</p>
  <span>33</span>
</div>

反例:

<div>
  <p>fa</p>
     <span>33</span>
</div>
  1. CSS內部命名應該有意義
    正例:
.conceal{
  border:none;
}
  1. 每個選擇器及屬性獨占一行
    正例:
.btn{
   width: 100px;
   height: 30px;
}
  1. 多使用相對寬度,少用絕對寬度
    這樣的目的主要是更容易適配不同瀏覽器及屏幕。

項目地址

click here

PSP表格

PSP2.1 Personal Software Process Stages 預估耗時(分鍾) 實際耗時(分鍾)
Planning 計划
• Estimate • 估計這個任務需要多少時間 7day 8day
Development 開發
• Analysis • 需求分析 30 30
• Dicussing & Design Spec • 討論交流 & 設計文檔 30 40
• Design Review • 設計復審 20 10
• Learning • 學習新知識 60 80
• Coding Standard • 代碼規范 30 30
• Coding • 具體編碼 2500 3000
• Code Review • 代碼復審 30 30
• Test • 測試 30 20
Reporting 報告
• Test Repor • 測試報告 30 30
• Size Measurement • 計算工作量 30 20
• Postmortem & Improvement Of The Prototype • 事后總結, 並提出過程改進計划 30 20
合計 2820 3310

成品展示

  1. 主頁
    由頭部和側邊導航欄和主體三部分,主題采用輪播圖進行網站的推銷介紹(笑)。


    可以在頭部搜索框快速搜索,根據標題模糊查詢,得到查詢結果的列表。


    每個條目顯示標題、摘要、關鍵詞、會議、時間的信息,點擊詳情后可以觀看更詳細的內容。


    詳情頁內的關鍵詞里每個關鍵詞都可以點擊,點擊后可以跳轉到包含該關鍵詞的論文列表。


    另外,在論文列表和詳情頁都可以刪除該論文。
  2. 高級搜索頁
    點擊側邊欄的高級搜索可以到高級搜索頁面,可以進行標題、摘要、關鍵詞的模糊或精確查詢,還可以選定時間區間和會議,默認是2000-2020和三大會議都查詢(如果把三個會議都取消掉再查詢,會彈出提示信息不讓你查詢)



    順帶一提,這個分頁是可以用的,是真的分頁。
  3. 熱詞統計頁
    點擊側邊欄的熱詞統計后,可以顯示熱詞top10,並且可以選擇查看某個會議、某個年份區間的熱詞top10。


    熱詞top10下面還有對應上面top10的詞雲,點擊某個關鍵詞詞雲還可以跳轉到對應的論文列表。


    點擊柱狀圖中某個柱形,還可以查看對應的這個熱詞的熱度走向圖,並且可以選擇查看不同會議的走向。

  4. 熱詞圖譜頁
    點擊側邊欄的熱詞圖譜可以到這個頁面,展示的是所有會議的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是一個效率高、樂於助人的隊友,時常能提出很好的點子,跟他合作結對編程又充實又得到了成長,吸取了經驗。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM