OO第一單元總結

来源:https://www.cnblogs.com/adamding/archive/2019/03/26/10599441.html
-Advertisement-
Play Games

第一次作業 第一次作業需要完成的任務為簡單多項式導函數的求解。 思路 因為僅僅是簡單多項式的求導,所以求導本身沒有什麼可說的,直接套用冪函數的求導公式就行了,主要的精力是花在了正則表達式上。這裡推薦兩個網站: https://github.com/ziishaned/learn regex http ...


第一次作業

第一次作業需要完成的任務為簡單多項式導函數的求解。

思路

因為僅僅是簡單多項式的求導,所以求導本身沒有什麼可說的,直接套用冪函數的求導公式就行了,主要的精力是花在了正則表達式上。這裡推薦兩個網站:

https://github.com/ziishaned/learn-regex

https://regex101.com

前者可以用來學習正則表達式的語法,後者則提供實時的正則表達式匹配,方便進行調試和驗證。尤其是後者,能大幅提高編寫正則表達式的效率和正確性,省去了每次都得在IDEA里運行一遍的麻煩。

用正則時有一點需要註意,那就是大正則是不可取的。我一開始就是企圖用一大串正則匹配整個輸入,結果當時是爆棧了。合理的做法應當是每次只find()一個Term,以及通過Term與Term之間的連接關係判斷合法性。

在數據結構方面,我一開始用的是ArrayList,但在後來優化的時候發現合併非常麻煩,於是果斷放棄,學習並採用了HashMap。通過將指數作為Key,可以快速地找到指數相同的項,以實現合併同類項的目的。

程式結構分析

diagram1

由於剛接觸Java語言,也不太懂什麼是面向對象思想,所以程式整體來說還是比較C type的。也可能是由於本次作業比較簡單,所以也並沒有用到繼承、介面之類的東西。從類圖中可以看到,一共也就兩個類,其中PolyDiff完成主函數、預處理、合法性判斷等任務,而Term則實例化出多項式中的每一項,保存繫數和指數,並提供diff()求導方法。

度量分析

metrics1

可以看出個別方法複雜度過高,這很不OO。下次應當多註意抽象以及代碼重用,避免一個方法或者類的過於臃腫。

關於BUG

公測未被查出bug。在互測階段,我第一個發現的bug是自己的bug,其原因在於,我判斷合法性的做法是將匹配了的每一項用"#"替換掉,最後看除了" "、" \t"、"#"之外是否沒有其他的字元。然而,我忽略了輸入一開始就含有"#"的可能,但這種可能性非常小,以至於我認為只要不仔細閱讀我的代碼,基本上是不可能歪打正著的。遺憾的是,最終還是有一位十分認真的同學,(我猜)在一行一行通讀了我的整個代碼後,居然還真的發現了這個bug……我是服氣的,真的太強了orz

至於我查別人的bug,都是用的我寫作業時自測發現了bug的樣例,因為我相信這樣的樣例會具有一定的殺傷力和普適性。事實證明,我的確能用這種方法測出很多別人的bug,於是也就沒有再結合他人的代碼設計結構來設計更多的測試樣例。

第二次作業

第二次作業需要完成的任務為包含簡單冪函數和簡單正餘弦函數的導函數的求解。

思路

第二次作業新引入了正餘弦函數,乍看複雜了許多,但其實還是可以用套公式的辦法死做,然而代價就是毫無擴展性可言。

對於每一項及其導函數,都可以化為冪函數和正餘弦函數的冪次的乘積這種標準形式,那麼Term就相應擁有了繫數、冪函數及正餘弦函數的指數這四個屬性。除了正則表達式匹配和求導規則有一些變化,其餘與第一次作業並無太大區別。

值得註意的是,這次HashMap的Key我採用的是將冪函數及正餘弦函數的指數拼接成一個字元串,併在相鄰指數之間用"|"分隔。如此一來,便可省去重寫equals()和hashcode()的麻煩,然後像第一次作業一樣合併同類項。

程式結構分析

diagram2

程式結構大體類似於第一次作業。

度量分析

metrics2

合法性判斷的方法還是有些冗長了,可能是因為其中包含了一些對輸入進行預處理的操作,可以考慮將這部分單獨抽離出來。

關於BUG

在吸取了上一次作業的教訓後,我捨棄了替換捕獲組方法,而是根據本次匹配起點是否為上一次匹配的終點,以及最後一次匹配的終點是否為字元串的末尾,來判斷輸入的合法性。最終在公測和互測中都未發現bug。

發現別人程式的bug依然採用上一次作業的方法,果然又查出了不少bug,大多是對於非法的輸入沒有輸出WRONG FORMAT!

第三次作業

第三次作業需要完成的任務為包含簡單冪函數和簡單正餘弦函數的導函數的求解(支持因數嵌套在三角函數因數中)。

思路

正如之前所說的,套公式的做法是無法解決任意層嵌套的問題的,因此整個程式架構必須重構。在這裡我採用的是遞歸下降的方法,規定好每種函數、組合的求導法則,將嵌套的內容看做一個整體,留給下一層遞歸處理,每次只判斷當前層的合法性併進行相應的求導。

在優化方面,僅僅是剔除了冗餘的0、1、括弧、正負號等等,在同類項合併和恆等變換方面未能進行更多的處理,其原因和求導方法的返回值有關。由於我在一開始設計的時候就直接把每個因數的求導結果當作字元串保存,所以整個表達式求導的過程就相當於是字元串按一定規則轉化和拼接的過程。這樣做的好處在於簡答、直觀、不易出錯,但弊端也很明顯,那就是很難做進一步優化,因為對字元串中的內容是無法進行插入、刪除、替換、排序或合併等操作的,除非像讀取輸入那樣再一次對字元串進行分析。由於時間有限,我沒有那樣做。其實更好的方法是將求導的結果也作為某一個類的實例,方便對其做進一步的處理。

程式結構分析

diagram3

如圖所示,本次作業我用到了面向對象中的繼承,有必要這樣做的原因有三:

  1. 每個子類都需要toString()方法,以返回該項因數自身的字元串。由於這個方法對於每種因數都一樣,所以應該在父類中統一實現。
  2. 每個子類都需要實現各自的diff()方法,因為每種函數或組合都有自己的求導規則。
  3. 每個子類都繼承於Factor類使得不同類型的因數可以放在一個ArrayList中一起處理。

至於Term,它並不是因數,只是Expr的組成部分,所以單獨成為一類。

通過繼承這種面向對象的思維方式,我們程式的結構更加清晰,功能更加強大,最重要的是,擁有了可擴展性。

度量分析

metrics3

果然越複雜的程式,要做到均衡控制每個方法的複雜度就越難。主要的問題依然出在輸入分析、預處理以及合法性判斷上,儘管這次我將他們分離了開來。至於有沒有必要以及如何進一步拆解,還有待研究。

關於BUG

本次作業依然沒有被查出任何bug。

在查別人的bug方面,為瞭解放勞動力,這次我選擇寫腳本進行批量測試。我用到了Python中一個強大的第三方包——SymPy,可以進行複雜表達式的求導運算以及判斷兩式是否等價,這也是我的"簡化版評測機"的主要原理,即將Java程式的輸出與SymPy的輸出進行比對。顯然,該評測機無法對非法輸入給出評判。而測試用例本身依然是我自測時手動構造的測試集,按行讀取便可進行批量測試,威力極大,效率奇高。

總結與建議

第一單元總體還是比較入門的,重點在於熟悉Java語法特性、建立面向對象思維,為日後的多線程編程打好基礎。

對於我個人而已,學習了Java正則表達式、BigInteger類、HashMap、重寫與重載、繼承與介面等等技術,並且慢慢開始理解了層次化架構和麵向對象技術的優越性。總體感覺Java還是比C/C++要方便的多,基本上只要是你能想到的功能,總有類或者第三方包能為你提供解決方案。而這就需要我們有查找資料自學的能力,無論是看技術博客還是閱讀官方文檔,再加上自己多動手實踐,相信很快就能掌握一項新的技術,併在作業中發揮其功能。

此外,通過Checkstyle對代碼風格進行規範也是比較有效的措施,基本上不會再寫出會令人抓狂的代碼了。但是其中每行最多80個字元的限制我實在覺得不太合理,尤其是涉及正則表達式的時候,往往是硬生生地把一句邏輯連貫的代碼拆成多行。個人認為在閱讀代碼時,莫名其妙的換行比一行稍長的代碼體驗更糟。建議將每行的字元數上限改為100~120。

對於面向對象的理解可能還是只是停留在表層,甚至會有一些誤解,這就需要進一步的學習和練習,在一次次實踐中總結經驗與教訓。希望以後能寫出更加OO的程式。


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

-Advertisement-
Play Games
更多相關文章
  • 十一大行為型模式之九:備忘錄模式。 簡介 姓名 :備忘錄模式 英文名 :Memento Pattern 價值觀 :凡事要有備份 個人介紹 : Without violating encapsulation,capture and externalize an object's internal st ...
  • 通過第一單元的學習,首先是對面向對象程式設計思想有了一個大致的認識。其次對於面向對象語言的各種概念和機制有了大致的瞭解併進行了應用(如類、方法、繼承、介面、try-catch機制等)。通過自己課下練習、與同學討論和在課上通過老師對作業的總結講解,能夠明確感受到這樣一種思想與之前接觸的面向過程的一些程... ...
  • OO第一單元(求導)單元總結 這是我們oo課程的第一個單元,也是意在讓我們接觸瞭解掌握oo思想的一個單元,這個單元的作業以求導為主題,從一開始的加減多項式求導再到最後的嵌套多項式求導,難度逐漸提高,編程思想也逐步深入面向對象,如果說前兩次作業還可以用C語言的面向過程的思想去對付,那麼第三次作業可以說 ...
  • 面向方法的數據集緩存 使用了autofac做為ioc容器,使用Autofac.Extras.DynamicProxy2作為方法攔截器,緩存面向方法,直接在方法上添加CachingAttribute特性即可。 緩存註冊流程 1. 關於方法攔截器 1. 緩存名稱設計 1. 添加ioc 1. 添加攔截器與 ...
  • [TOC] 總 本博文是2019年北航面向對象(OO)課程第一單元作業(多項式求導)的總結。三次作業的要求大致如下: 第一次作業:簡單冪函數的求導,如 $1 + x^5 + 4 x^3$ 第二次作業:簡單冪函數和簡單正餘弦函數的求導,如 $ 5 sin(x)^2+5 cos(x) cos(x)+12 ...
  • 構造方法 概念: 又叫 構造器,區分於傳統的方法,是一個在創建對象時被系統自動調用的特殊方法 作用: 一:為對象進行初始化(成員變數)的工作 二:為對象在堆記憶體中開闢獨立的記憶體空間 定義格式: 訪問修飾符 方法名(){ } 用法: 只能通過new關鍵字進行調用 註意事項: 一:方法名必須和類名保持一 ...
  • 一、前三次作業內容分析總結 前言 前三次作業,我提交了三次,但是有效作業只有兩次,最後一次作業沒能實現多項式求導的基本功能因此無疾而終,反思留給後文再續,首先我介紹一下這三次作業,三次作業圍繞著多項式求導展開,輸出目的都是一致的,即對輸入的多項式進行求導,將求導結果列印到顯示屏,作業難度遞增,每一次 ...
  • 記得比較早使用手機掃碼登錄是網頁版微信,這種免去輸入繁瑣的賬號密碼,拿起手機掃一掃就可以登錄的方式一開始還是比較驚艷的,確實使用起來很方便。 那它是如何實現的呢?我們來簡單研究下。(以淘寶網二維碼登錄為例) 首先,任何一個二維碼表示的都是一串字元串。 我們打開淘寶登錄頁面: "https://log ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...