共生性

共生性


什麼是共生性


共生性是拉丁文,意思是「同時出生」。


當兩個模組的生命週期糾纏在一起,

我們就可以說它們具有「共生性」。


其中一個做出改變時,另一個就必須隨之改變。


靜態共生性 (static connascence)


描述模組在原始程式碼的連結,即在編譯階段中

有哪些知識能夠跨越模組邊界共享。


名稱共生性 (connascence of name)


暗示相連的模組,為了引用相同的東西,

必須對其名稱達成共識。


  • 得讀取或更新的變數名稱
  • 想呼叫的方法名稱
  • 想執行的服務名稱

1
2
3
4
5
6
7
<?php

function greet($name) {
echo "Hello, $name!";
}

greet('world');
  • 3 和 4 行對變數名稱 $name 取得共識。
  • 3 和 7 行對方法名稱 greet 取得共識。

上述範例中,若要改變變數或方法名稱,

必定會影響其中的兩行程式碼。


也能套用到其他層級的模組,

比如多個類別互動時的公開方法與屬性。


甚至可以應用到網路服務,

例如允許的 HTTP 方法。


型別共生性 (connascence of type)


當兩個元件針對特定的型別達成共識時,

就會產生「型別」共生性。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;

public class SayHello
{
public static void Greet(string name)
{
Console.WriteLine($"Hello, {name}!");
}

public static void Main()
{
Greet("world");
}
}
  • 5 和 12 行中,只知道變數名字還不夠
  • 必須使用相同的型別

意義共生性 (connascence of meaning)


若某個值會跨越邊界傳送,並存在特殊意義,

那麼它們就存在意義共生性。


1
2
3
4
5
6
7
8
9
10
using System;

public class ReferralService
{
public static void SendReferral(Customer customer, string email)
{
Console.WriteLine($"Sending referral to {email}");
customer.SetMembershipStatus(6);
}
}
  • 8 行的 MemberShipStatus 被設定成 「6」
  • 「6」到底代表什麼意思?
  • 我們或許不得而知,ReferralService 和 Customer 顯然都曉得

1
2
3
4
5
6
7
8
9
10
public enum MembershipStatus
{
Inactive = 0,
Basic = 1,
Active = 2,
Premium = 3,
VIP = 4,
Gold = 5,
Referrer = 6
}

我們試著引入 Enum


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ReferralService
{
public static void SendReferral(Customer customer, string email)
{
Console.WriteLine($"Sending referral to {email}");
customer.SetMembershipStatus(MembershipStatus.Referrer);
}

public static void Main()
{
Customer customer = new Customer(1);
SendReferral(customer, "test@test.com");
}
}

改寫原本的演算法


演算法共生性 (connascence of algorithm)


某種方面來說,演算法共生性很像意義共生性。

只是把共享的知識再拉高了一個層級。


一個典型例子是兩個模組交換加解密資料。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
using System.IO;
using System.Security.Cryptography;

public class StorageService(IStorageRepo storageRepo)
{
public static void UploadFile(string filePath)
{
var data = File.ReadAllBytes(filePath);
var checksum = ComputeMD5Checksum(data);

storageRepo.Upload(data, checksum);
}
}

References


ʕ •ᴥ•ʔ:Thank you

Share