軟體架構
筆者在看整潔架構實作篇的時候,階層式架構在開發是滿常用的基本設計,但這一個部分其實有一些弱點或是不足地方,不過還是稍微寫一下筆記專門探討這一部分
在軟體開發領域中階層架構算是滿常用的的模式,筆者舉例兩種常見的例子如下
- 應用程式階層架構
- 網站MVC架構
應用程式階層式架構:在許多軟體應用程式中,常見的架構是將系統分為多個層次,包括用戶介面層、業務邏輯層和資料存取層。用戶介面層處理與使用者的互動,業務邏輯層處理應用程式的邏輯運算,而資料存取層則負責與資料庫或其他資料源進行交互。
網站開發中的MVC架構:MVC(Model-View-Controller)是一種常見的階層式架構,用於開發網站和Web應用程式。Model負責處理數據邏輯和資料存取,View負責處理使用者介面的呈現,Controller負責處理用戶輸入和控制流程。
應用程式階層架構:三層架構
三層式架構的最底層是資料庫,表示層、依賴業務層,業務層又依賴資料存取層。
優點:
- 實現分離關注點
- 提高程式的可讀性
- 可維護性和可擴展性
- 它使不同層次的程式碼可以獨立地進行修改和測試
- 同時還能夠支援多種用戶介面和資料庫技術的彈性組合
缺點
- 耦合性:三層架構中各層之間通常存在相依性,尤其是業務邏輯層和資料存取層之間的耦合性較高。這使得修改或變更其中一個層次可能需要對其他層次進行調整,增加了系統的脆弱性和維護成本。
- 過度設計:三層架構常常在設計初期就將系統劃分為三個固定的層次,這可能導致過度設計。當系統需求變化時,可能需要進行大量的重構和修改,增加了開發和測試的時間和成本。
- 學習成本:三層架構通常需要開發人員具備多層次的技術知識和技能。對於新入職的開發人員或團隊成員來說,需要花費一定的時間和努力來學習和理解這種架構。
筆者在看實作整潔架構部分,作者該架構最基礎的是資料庫而不是領域邏輯,深深有感觸是因為過往筆者在傳產或是資訊公司的時候,許多地方在需求釐清梳理部分,除了要理解業務流程以外還要定義出資料表的欄位紀錄與表有哪些?
最後筆者覺得文中有一點還不錯的是建模主要對象是針對行為,而不是狀態,對所有應用程式來說狀態很重要事情,但行為才是導致狀態改變原因,也是業務邏輯驅動力。
以下是三層架構的基本例子:
using System;
namespace Model
{
public class Member
{
public string UserId { get; set; }
public string Password { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Model;
namespace Repository.Interface
{
public interface IMemberRepository
{
Member GetByMember(string userid, string password);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Model;
using Repository.Interface;
namespace Repository
{
public class MemberRepository : IMemberRepository
{
public List<Member> members = new List<Member>() {
new Member{ UserId = "test001",
Password = "test002",
Name ="Eddie",
Email = "aaa@gmail.com"}
};
public Member GetByMember(string userid, string password)
=> members.Where(m => m.UserId == userid && m.Password == password).FirstOrDefault();
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Service.Interface
{
public interface IMemberService
{
bool Login(string userId, string password);
}
}
using Repository.Interface;
using Service.Interface;
using System;
namespace Service
{
public class MemberService : IMemberService
{
public readonly IMemberRepository _memberRepository;
public MemberService(IMemberRepository memberRepository)
{
_memberRepository = memberRepository;
}
public bool Login(string userid, string password)
{
var member = _memberRepository.GetByMember(userid, password);
if (member == null)
return false;
return true;
}
}
}
using NUnit.Framework;
using NSubstitute;
using Repository.Interface;
using Model;
using Service.Interface;
using Service;
namespace Tests
{
[TestFixture]
public class MemberTests
{
private IMemberRepository _memberRepository;
private IMemberService _memberService;
private Member _setReturnMember;
[SetUp]
public void Setup()
{
_memberRepository = Substitute.For<IMemberRepository>();
_memberService = new MemberService(_memberRepository);
_setReturnMember = new Member()
{
UserId = "test001",
Password = "test001",
Name = "test",
Email = "abc@gmail.com"
};
}
[Test]
public void Login_ReturnSuccess()
{
string userid = "test001";
string password = "test001";
_memberRepository.GetByMember(userid,password).Returns(_setReturnMember);
//任一參數並回傳多值做法
//_memberRepository.GetByMember(Arg.Any<string>(), Arg.Any<string>()).ReturnsForAnyArgs
// (_setReturnMember1,
// _setReturnMember2);
bool result = _memberService.Login(userid, password);
Assert.IsTrue(result);
}
[Test]
public void Login_ReturnFail()
{
string userid = "test001";
string password = "test002";
_memberRepository.GetByMember(userid, password).Returns(m => null);
bool result = _memberService.Login(userid, password);
Assert.IsFalse(result);
}
}
}
關於偷吃步
作者在文中當中提到有一個叫做破窗理論。
筆者在看破窗理論覺得很有意思是,在軟體開發領域上只要有人開始偷偷跨層或是求方便的狀態,一旦這種先例打開之後,就會被普及接受,因為後面的人在看這程式或是專案的時候,會一樣畫葫蘆繼續開發下去,就會變得相當嚴重。
詳細參閱:https://zh.wikipedia.org/zh-tw/%E7%A0%B4%E7%AA%97%E6%95%88%E5%BA%94
探討架構層的缺陷
在實作的整潔架構當中有提到幾點我滿認同的以下:
1.沒辦法在套件中凸顯出功能邊界出來,以ASP.net MVC為例,在控制器裡面加入UserController、Domain領域當中加入UserService、UserRepository、這些類別檔案沒有使用其他結構輔助亂起來,應用程式不相關功能產生副作用。
2.看不出使用案例,書裡面有提到說AccountService、AccountController實作哪些使用案例是看不出來的。
六角形架構分別有
- 實體
- 使用案例
- 輸出入轉換Port
- 輸出入轉接器
來分別探討這些我們常見問題
待續中
參考範例
https://github.com/bda605/hexagonal-architecture-acerola
元哥的筆記