天天看點

軟工實踐結對作業二

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

這個作業屬于哪個課程 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
• 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

成品展示

  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是一個效率高、樂于助人的隊友,時常能提出很好的點子,跟他合作結對程式設計又充實又得到了成長,吸取了經驗。