BUAA_OO_第四單元

来源:https://www.cnblogs.com/iff0/archive/2020/06/15/13130169.html
-Advertisement-
Play Games

一、UML解析器設計 ​ 先看下題目:第四單元實現一個基於JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的對象(元素)可能與同級元素連接,也可與低級元素相連形成 ...


一、UML解析器設計

​ 先看下題目:第四單元實現一個基於JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的對象(元素)可能與同級元素連接,也可與低級元素相連形成層次關係

輸入:上述三UML圖的邊集(非實體元素)與點集,上下層級元素通過_parent隱式鄰接。值得註意的是,不同於前兩個單元,我們終於回歸了離線演算法OFFLINEI/O通過一行END_OF_MODEL分隔,處理難度減小了

輸出:針對給出的_name索引到相應的UML元素查詢相關對應圖中信息,複雜的problemhw15中對迴圈繼承的判斷,其他的都能不使用高級演算法解決掉

​ 下圖是我對本單元作業設計的類圖,因為三次作業都是這個架構,下文只按解析器構造流程順序分析。btw感謝肖同學的排雷帖,可見我對UML的理解不夠深入,UMLAttribute可以出現在順序圖中,不應該簡單歸入類圖元素的子類,不過我這樣還是能活過本單元的

信息轉換——適配器模式

​ 我構建了抽象類MyEle,以及三個子抽象類對應三種UML圖中的元素,因為介面給出的結點(對應實體的元素)沒有鄰接結點的信息,我有必要自定義類來保存這些信息。能將這種“一些"現存的對象"放到新的環境中,而新環境要求的介面是現對象不能滿足的”問題解決的是適配器模式

public class MyAdapt {
    //適配器用於轉換的類
    public static MyEle as(UmlElement e) {
        switch (e.getElementType()) {
            case UML_CLASS: {
                return new MyClass((UmlClass) e);
            }
            case UML_ASSOCIATION: {
                return new MyAssc((UmlAssociation) e);
            }...
//
public abstract class MyEle {
    //My*類對UmlElement對象有一個依賴,MyEle實現基本信息介面,其他由子類分別考量
    private UmlElement ele;
    public MyEle(UmlElement e) {
        this.ele = e;
    }...

​ 在UmlInteraction構造函數中,我首先將傳入的UmlElement通過MyAdapt“轉換”成My*對象,後者可以從前者中只存儲我們關心的信息,一些可以忽略的元素UmlEvent / UmlEndPoint等直接在這裡過濾掉

建圖

​ 有了這些準備工作開始建圖,以類圖為例(另兩類圖如法炮製),通過.mdj解析,邊集通過_parent / _reference / UML元素表示,提取後完成建圖。我對作業中涉及的所有的UmlElement,包括邊集UMLAssociation / UMLGeneralization等都適配自己的類,當然這可有可無,我這樣做是為了遍歷一遍MyEle對象就完成建圖,看起來清晰一點。類圖中的頂級元素是類與介面,都管理著方法與屬性,StarUML中可以對二者進行很多相同操作,有必要為二者創建父類ClassLike(類實體)來複用代碼

​ 根據輸入模式,我們在解析器中需要管理按_name索引的Class / StateMachine / Interaction等集合,並且索引查詢中要進行有效與重覆檢查。我為了復用代碼採用了泛型容器,分別用Hashmap / Hashset實現有效_name查找表與重覆_name

public class MySet<T> {
    private HashMap<String, T> na2ele = new HashMap<>();
    private HashSet<String> dupName = new HashSet<>();
    public void add(T t) {
        if (t instanceof MyEle) 
            if (na2ele.containsKey(t.getName())) dupName.add(t.getName());
            else na2ele.put(t.getName(), t);
    }
    public boolean contains(String s) { return na2ele.containsKey(s); }
    public boolean isDup(String s) { return dupName.contains(s); }
    ...

​ 根據輸入,查詢請求關心ClassLike自身的層次或直接關聯關係ClassLike間接繼承/實現的關係,後者如“類的頂級父類 / 實現的全部介面”需要ClassLike繼承鏈上的信息。沒有迴圈繼承時繼承鏈為樹形結構,由此,我在MyClassLike定義addFather / getFather / update繼承相關抽象方法。updateextendsimplementsClassLike進行update後再合併信息,置為更新過的狀態,是遞歸式搜索

​ 輸出方面,通過與同學交流可以記憶化搜索(查詢時更新),但是這是個OFFLINE問題,同時考慮到題目的數據規模1e2.6,小,在完成建圖之後直接對所有類update,全部元素更新後再進行查詢也沒問題,這樣不用每個查詢方法都先update一下了

PreCheck

hw15要求進行有效性檢查,上文中查詢前update顯然要放到R002 / R003之間,有效性以_id / _name重覆,_visibility等檢查為主,很簡單;R002檢測迴圈繼承,輸出繼承環路上所有元素,當然不用求出環路,只要求出所有環路上的元素。MyEle處在繼承環路上 iff 其處於某階數大於1的強連通分量上或本身存在自環或一次以自身為源點的搜索經過本身1次以上,故可使用TarjanBFS來檢查

二、OOP心路歷程

​ 談到架構設計及OO方法理解的演進,我認為自己本學期確實有長進,起碼前兩個Unit次次重構,但後兩個Unit都是先好好分析設計結構再寫的,而且都不很複雜,所以都沒有重構

Unit1為層次化設計,hw1 / hw2是純純的面向過程,hw3中利用工廠模式根據實際中的實體為表達式中的對象建立了具有繼承層次關係的類,通過將求導以及化簡操作作為抽象方法,使得因數,表達式啥的都能按照自己的求導法則各自計算導數、化簡,輸出通過覆寫toString(),這是我首次在作業中體會到面向對象中多態的優勢。

Unit2為多線程設計,代碼結構很簡單,採用簡單的生產-消費者模式都行,主要還是通過Java庫及保留字實現Java線程的同步與互斥,這塊一直理不太清又很難調試,所以又重構了好多次,可以說我也是初次接觸線上演算法問題,電梯調度的優劣是跟數據相關的,其實有點玄學,在這裡我初步瞭解了Java的異常機制,這是保證魯棒性的方法之一,Java中還有封裝好的ReentrantLock可重入鎖等鎖,我也做了瞭解

Unit3為規格設計,需要根據JML封裝官方包中的介面,首先得說JML表意很準確,不用像指導書般反覆研究,這個Unit大家實現的介面功能都是一樣,但方法與效果不盡相同,面向對象中就是通過這樣的封裝實現代碼的模塊化,調用者很難為封裝好的方法優化,作為實現者有義務實現高效的封裝。面向過程和麵向對象肯定不是對立的,我們實現的代碼對外是屏蔽掉的,所以在作業中我在底層函數用了很多面向過程風格的代碼

Unit4為模型化設計,我們接觸的UML脫離了Java,描述的是對象、屬性、狀態等,更加接近面向對象的本質,作業方面空間很大,由於hw13就理好了層次,後續輕鬆拓展,還第一次使用了泛型容器,節約了很多代碼量,充分封裝各個層次的操作以模塊化

三、測試理解與實踐

​ 當然我印象最深刻的是多線程程式測試,程式運行結果與環境相關,在測試出現問題後很難通過程式本身找到病因,我使用JProfiler + println()才能逐步確定程式卡在了哪裡

​ 測試分兩方面,一是驗證程式的基本功能,二是對極限數據或異常輸入測試,前者通過隨機生成樣例數據或JUnit單元測試法或對拍實現,後者如電梯換乘調度測試,特殊表達式求導,給定數據規模下複雜度最高的數據。我認為註重後者或許對我們更有價值,反正我的Bug都出在極限情況...還有一種測試就是對優化過的代碼進行測試,一定得用修改前版本對拍一下,屬實對這一點有ptsd

JUnit對我而言很好用,@Before / @Test / @After完整構建了數據生成、斷言測試、錯誤分析的測試流程,還在同一項目下就能用,舒服啊

四、收穫總結

​ 首先我在本學期通過Java認識到面向對象的印象深刻的特征:封裝與多態

​ 封裝定義為隱藏對象的屬性和實現細節,僅對外公開介面,我最開始對每個屬性幾乎都寫了get / set,但這樣屬性的隱藏原則就沒意義了,我理解的封裝是沒有需求就不開放屬性的查詢或方法的調用,所以屬於對象“份內事”的方法也儘量用private修飾。封裝的優勢顯然,首先封裝隱藏了屬性,保證了程式的數據安全,封裝方法,可以使程式設計更加模塊化,比如Unit4中可將三種圖的查詢分派給三種管理類,這樣也能降低類的平均複雜度,還有一點是封裝的代碼拓展性強,需要改變程式功能時,調用者往往不用改寫,只需對封裝的對象中的數據結構與方法進行修改,這也是課程迭代開發模式下的要求。當然,既然有這個信息隱藏原則,調用者就很難根據實際問題對封裝對象作出調整,導致封裝對象已經很難有優化的空間,所以使用封裝時,調用者得對對象有一個大體的瞭解,比如在Unit3中我因為對Hashmap的底層實現不瞭解,初始容量過大引發了隱患;實現者則需合理利用時空資源保證程式的整體良性

​ 多態,我理解的是同一類型對象引用在運行時可以使用不同的方法以實現“多種形態”,一種形式是子類Override方法後使用父類類型引用,還可以是由不同類實現的介面。通過多態在Unit1實現表達式中不同因數的求導,在Unit4中可以讓數據結構不同的Class / Interface(單/多繼承)共用一份Tarjan代碼,多態巧妙在我們無需去if-else所引用的對象實際是什麼類型,調用的方法採用對應繼承鏈上最近的版本,所以多態中想要擴展新子類很簡單,只需要符合引用者的行為邏輯,引用新子類的對象則無需修改代碼

​ 當然一些別的特征也很酷,我們可以通過繼承復用父類的代碼,也可以通過泛型類來複用代碼,並且實現類似多態的效果,不過泛型類在構造傳入類型時,其所管理的類型就確定了,所以我覺得泛型倒有一點c/c++#define的意思


​ 不難看出,上面這些特征,無論是類也好,介面也好,其共性是對對象行為範式的一種抽象,OO語言不同於PO語言的一點就是它給了一套這種抽象的機制,所以面向對象編程更貼近實際,我們代碼的結構往往對應實際中的邏輯關係,可能這也是Java的優勢,雖然不精煉,但很直觀易懂

​ 在理論網課 / 實驗課中,我也學到了OO設計模式與原則,OO的可維護性強,很適合於迭代開發與複雜系統的整體設計,學習OO編程思想,更深入地理解Python / C++等的OO機制了

五、我的改進意見

  • 看到這麼多同學吐槽實驗課我就放心了,我認為實驗課有必要給同學們一定的反饋,具體的形式可以是編程性實驗之後可以在平臺上像作業一樣瞭解測試情況並且進行Bug修複

  • 感覺後兩Unit對可維護性要求降低了,Unit1中嵌套的出現打破了原本簡單的表達式到因數的層次關係,Unit2中多部電梯的出現改變了控制類的數據結構,也改變了線程同步的條件,而Unit3 / 4在迭代開發中基本是跟隨指導書在上一次作業中多寫些方法增加功能就okay了,反正就是對原先的作業架構的衝擊力不夠大,應該提高難度,btw程式高效性也很重要,希望後兩個Unit能開啟性能分

  • Unit3可以放到前面,體現出類規格,層次間的規格

  • 互測本意應該是驅動大家學習其他同學代碼中的設計策略吧,建議發動Hack的時候得提交自己發現的Bug的位置,防止互測變成純黑箱互測

六、網課學習體會

​ 條件艱苦的線上網課,頗懷念線下的課堂氛圍和peer pressure呢

​ 感謝仍離同學們最近的老師與助教們~

​ 馬馬虎虎算是入門了OO,鐵鐵們,共勉


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前端即網站前臺部分,運行在PC端,移動端等瀏覽器上展現給用戶瀏覽的網頁。多數後端開發人員從事於構建工作應用程式背後的實際邏輯。前後端需要相互配合,共同完成一個項目。那到底什麼是前端?什麼是後端呢? 接下來小編帶你一起來瞭解前端與後端技術的區別。 一、什麼是前端開發? 1、前端概念 前端即網站前臺部分 ...
  • 許多小伙伴關於WEB前端工程師是很有些想法的,畢竟是高薪又面子,誰都想瞭解一下,一探究竟。又不少人都個筆者留言,問WEB前端工程師要做什麼作業,有提升空間嗎,本文就是為了回答這個問題而誕生的,現在我們就一起來討論一下,WEB前端工程師要做什麼,有提升空間嗎,這個話題。 1:在知道WEB前端工程師要做 ...
  • 在我們做應用系統的時候,往往都會涉及圖表的展示,綜合的圖表展示能夠給客戶帶來視覺的享受和數據直觀體驗,同時也是增強客戶認同感的舉措之一。基於圖表的處理,我們一般往往都是利用對應第三方的圖表組件,然後在這個基礎上為它的數據模型提供符合要求的圖表數據即可,VUE+Element 前端應用也不例外,我們這... ...
  • 為元素添加on方法 Element.prototype.on = Element.prototype.addEventListener; NodeList.prototype.on = function (event, fn) {、 []['forEach'].call(this, function ...
  • config下麵的host不要動,只改動package.jsong下麵的host不要動,只改動package.json下dev即可 "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.d ...
  • <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcss.com/openlayers/4.6.5/ol.css" rel="st ...
  • 今天給大家介紹一下全球最大的男性交友網站:Github。 度娘是這麼介紹的: 拿人話說,就是程式員們可以把自己原創的代碼發上去,供別人免費使用。 放到我們小編屆,就是唐唐寫一篇文章,免費放到網上讓別人轉載,只要標個出處,誰複製都行。 作為回報……emm代碼的上傳者並沒有任何回報。 Github社區建 ...
  • 現象:el-input或者input標簽中,輸入空格無效,並不能加入到字元串中。 原因:眾多原因之一: 1. 首先,這是在vue項目中,那麼檢查el-input或者input外層包的dom元素。 檢查是否有el-menu這個元素包在了el-input外層或者input外層,如果有,那麼el-menu ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...