C言語-「高凝集度、低結合度」プログラミングのアイデア

1.定義

高凝集度と低結合度はソフトウェア工学の概念であり、設計の品質を判断するための基準です。これは主にオブジェクト指向設計であり、主にクラスの凝集度が高く結合度が低いかどうかに依存します。

2.コンセプト

カップリング:ブロック間接続とも呼ばれます。ソフトウェアシステム構造内のモジュール間の近さの程度の尺度を指します。モジュール間の接続が近いほど、結合が強くなり、モジュールの独立性が低下します。モジュール間の結合のレベルは、モジュール間のインターフェイスの複雑さ、呼び出しの方法、および送信される情報によって異なります。

凝集性:ブロック内接触とも呼ばれます。モジュールの機能強度の尺度、つまり、モジュール内のさまざまな要素が互いにどれだけ密接に組み合わされているかの尺度を指します。モジュール内の要素(名前間およびプログラムセグメント間)がより密接に関連している場合、その凝集性は高くなります。

いわゆる高凝集度とは、ソフトウェアモジュールが高度に相関するコードで構成され、単一責任の原則と呼ばれることが多い1つのタスクのみを担当することを意味します。

低結合の場合、表面的な理解は次のとおりです。モジュール間で、可能な限り独立させるための完全なシステム。言い換えると、各モジュールに特定のサブ機能を可能な限り独立して完了させます。モジュール間のインターフェースは、できるだけ少なく、シンプルにする必要があります。特定の2つのモジュール間の関係がより複雑な場合は、最初にさらにモジュールを分割することを検討するのが最善です。これにより、変更と組み合わせが容易になります。

3.達成する方法

C言語はプロセス指向であり、通常はコールバックメソッドを使用します。C ++オブジェクト指向で、高い凝集度と低い結合度を実現するには、インターフェイステクノロジが必要です。

高凝集度と低結合度を実現するには、モジュールを設計する必要があります。
      (1)各モジュール間の機能が明確である必要があります。
      (2)各機能モジュール間に実装される機能が重複してはなりません。
      (3)モジュールは相互呼び出しを許可されていません。
      (4)モジュール間呼び出しで一方向の呼び出しのみを許可する必要がある場合、つまりaがBを呼び出すことができる場合、BはAと呼ばれない場合があります。

      C言語の一般的な形式(1)-関数インターフェース:

グローバル変数の使用を避けてみてください。グローバル変数を使用せずにモジュール間でデータを転送する方法は?たとえば、他のモジュール(LEDディスプレイなど)では、ボタンの状態を知りたい場合、またはボタンの状態を設定したい場合、一般的な考え方はkeyFlagグローバル変数を定義することです。次に、LEDディスプレイモジュールとキーモジュールの両方がkeyFlagを直接操作し、モジュール間の結合を改善します。

これには多くの欠点があります。いつかボタンモジュールを他のプロジェクトに導入して使用する必要があるが、グローバルボタン変数がkeyStatusとして定義されているか、プロジェクトで定義されていない場合、この状態でボタンステータスを取得するにはどうすればよいですか。時間?グローバル名を変更したり、グローバル変数を再定義したりするのは面倒ですか?

したがって、外部呼び出し用のボタンモジュールで2つの関数を定義するだけで十分です。

u8_t  get_key_status(void)
{
    return  key_flag;
}

void  get_key_status(u8_t  flag)
{
    key_flag = flag;
}

ボタンの状態を知る必要があるモジュールは、上記の2つの関数を呼び出すだけでよく、ボタンモジュールで定義されたボタンの状態の変数名を気にする必要がないため、グローバル変数の使用が削減されます。

C言語の一般的な形式(2)-関数ポインター:

ソフトウェアは通常、ログ機能によって実現されるバックグラウンドログの記録機能を備えており、主なビジネスはビジネス機能によって表されます。

void log()
{
	printf("Logging...\n");
}


void business()
{
	while(1)
	{
		sleep(1);
		printf("Deal Business...\n");
		log();
	}
}


int main()
{
	business();
	return 0;
}

次に、バックグラウンドログ機能をアップグレードする必要があります。それを実現するにはどうすればよいですか?

一般的な考え方は次のとおりです。別の関数log2を記述してから、log in businessをlog2に変更します。それだけでは不十分ですか?

しかし、考えてみてください。メインのビジネスコードを簡単に変更するにはどうすればよいでしょうか。機能が小さいため、メインのビジネスコードを変更する必要がありますが、IQは非常に緊急性が高いと思いませんか?

別の言い方をすれば、コールバックを使用します。

#include <stdio.h>
#include <unistd.h>
 
void log1()
{
	printf("1 Logging...\n");
}
 
void log2()
{
	printf("2 Logging...\n");	
}
 
void business( void (*f)() )
{
	while(1)
	{
		sleep(1);
		printf("Deal Business...\n");
		f();
	}
}
 
int main()
{
	business(log1);
	return 0;
}

ビジネス関数は関数ポインタを受け入れます。ポインタが指す関数にはパラメータがなく、戻り値はvoidであり、ログ関数のプロトタイプに準拠しています。ビジネスのf()が対応する関数を呼び出すことができる限り。

log1を使用する必要がある場合は、log1をビジネスに渡し、アップグレードされたlog2を使用する場合は、log2を渡します。

このように、ビジネス機能は受信データを変更する必要はなく、自身の機能のみを考慮します。ユーザーは、ユーザーが呼び出すときにどのデータを渡すかをユーザーに決定させるため、汎用性と柔軟性が向上します。関数の。

(PS:https//blog.csdn.net/scottly1/article/details/34074723 ; https://blog.csdn.net/Chum_yang/article/details/82835610これらの2人のブロガーの考えと要約に感謝しますなぜなら、絵の時間、彼らのケースを引用して、ありがとう~~)

 

 

 

おすすめ

転載: blog.csdn.net/zwb_578209160/article/details/106429684