マイコン開発でのリンカ設定

C言語でマイコン開発を行っている中で、関数外で宣言した変数の値が書き換えられない現象に遭遇しました。

static bool _initializedA;           // A
static bool _initializedB = false;   // B

void init() {
  _initializedA = true;
  _initializedB = true;
}

上のようなコードで、Aは関数内で書き換え可能ですが、Bは書き換えされず、関数を抜けても _initializedB の値が false のままという内容でした。コンパイルおよび実行時にも警告やエラーが発生せず、最初理由がよく分かりませんでした。

原因はリンカの設定によるものでした。Bのほうは初期値ありなので.dataセクション(ROM)に配置され、リンカのデフォルトの設定ではROMからRAMへのマップが行われていませんでした。

実はこのときは普段使用しているものとは異なるマイコンでの開発であったため、開発環境も普段とは異なり、デフォルトのリンカの設定がこのようになっているとは知りませんでした。

C言語での開発はオープン系言語と比べると、このような点でも難しく感じます。せめて警告やエラーが発生すればもっと早く気が付けるのですが、言語知識だけでなく、経験や経験に基づく感も必要なようです。

初めてのCとC++

これまでの業務ではC#を使ってきました。
今回初めてCとC++に携わる機会があり、学習しました。
せっかくなのでModern C, C++ と言われる比較的新しいバージョンです。

C#を使い慣れているとCやC++ではロジックのコード量が増え、
こんなこともできないのか、と思う一方、
特にメモリの扱われ方などはより理解が深まりました。

ただC++は言語仕様としてもかなり複雑で、Cの次に学ぶにはとても難しい印象です。
なのでC++習得するには先にC#等を理解して、オブジェクト指向の特徴や、
最近の言語の機能、プログラミングスタイルなどを知った後のほうが、
C++を使ってどのような設計や関数を目指すべきかということがよく分かると思います。

RustもC++とよく比較されて人気があるようなので、
今後触れてみたいと思います。

初級ソフトウェア品質技術者 資格試験

11月に、初級ソフトウェア品質技術者 資格試験を受けました。
ソフトウェアの品質技術を身につけ、品質の向上を目的とした試験で、
ソフトウェアの品質向上に関する知識を体系的に学ぶ為に受験しました。

試験に関しては、初級試験の合格率は40%前後なので、きちんと学習しないと合格は難しいようです。
また今回の試験から新しいシラバス(Ver.3.0)となっており、出題範囲も広くなっています。
私の場合はシラバスの用語をピックアップしながら、テキストを読み進めるスタイルで学習しました。
実務で品質を扱っていないと用語や概念が難しい部分もありますが、
ソフトウェアのライフサイクル(企画~廃棄まで)を意識して、
今はどのプロセスの内容の事を指しているのかを把握する事が重要だと感じました。

学習した内容を生かして、
今後は社内のプロセス改善や品質向上に役立てていきたいと思います。

ASP.NET Core MVC

仕事で ASP.NET Core MVC を使用しました。
社内では既に実用していたのですが、
プロジェクトの作成や新規で導入を行ったのは、個人的に初めてとなります。

Razor構文やHTML、JavaScriptでwebページや処理を記述する事になるので、
慣れないと少しぎこちない部分もありますが、新鮮でした。
比較的新しいフレームワークなので、
例えばxxxControllerのxxxが、Viewsのxxxフォルダと対応したり、
1つのViewに相当するyyy.cshtmlがyyy()メソッドと対応したりなど、
フレームワーク側のサポートがあって使いやすいと感じました。

このようなサポートはその命名ルールを強制する事になるので、
開発者としては迷いが少なく助かります。
これをきっかけに、Web関連の知識や技術も学んでいければと思います。

C# オブジェクト初期化子でプロパティのプロパティを初期化

C#でオブジェクト初期化子という構文があります。
オブジェクトの作成時にアクセス可能なプロパティやフィールドに値を割り当てるもので、
例えば次のように書きます。

var person = new Person() {
    Name = "Taro",
    Id = 1,
};

これは以下と同等です。

var person = new Person();
person.Name = "Taro";
person.Id = 1;

メリットは初期化の内容が1箇所に集まることで、
初期化中に間違って別の処理が混入することが無いことです。
なので積極的に利用すべきですね。

初期化できるのはアクセス可能なメンバーに限定されるので、
例えば以下のケースはコンパイルエラーとなります。

var parent = new Parent() {
    Person = new Person(),  //Person プロパティはsetできないのでコンパイルエラー
};
class Parent {
    public Person Person { get; } = new Person();
}

class Person {
    public string Name { get; set; }  //プロパティ
    public int Id;  //フィールド
    public List<int> RelatedId { get; }

    //コンストラクタ
    public Person() {
       RelatedId = new List<int>() { 1 }; //要素"1"で初期化
    }
}

Parentオブジェクト初期化子内で、
Personプロパティのプロパティを設定したい場合は以下のように書きます。

var parent = new Parent() {
    Person = { Name = "Taro", Id = 1 }
};

ではList<int>に値を指定した場合はどうなるでしょうか?

var parent = new Parent() {
    Person = { Name = "Taro", Id = 1, RelatedId = {10, 20}}
};

RelatedIdはコンストラクタで初期化された値に値が追加され、
この場合、要素が{1, 10, 20}の要素数3のコレクションとなるようです。
あまり使いどころは無いかもしれませんが、覚えておくとどこかで役に立つかもしれません。

ソフトウェアの完成

製作しているソフトウェアが完成すると嬉しいものです。
でも完成のタイミングとはいつなのでしょうか?
実装が全て完了して、
仕様を満たしているか、動作は問題無いか等の確認を行い、
全て合格した場合に完成となります。

ただ動作テストの時にいろいろ気付くこともあり、
そのときに「この部分は使い勝手が悪い」「もっとこうしたほうが良い」など、
特にUI(ユーザーインターフェース)周りで改善案が浮上します。
私の場合はこの時点で挙がった改善案をtodoとして、
それらを解決した時点で完成としています。

デザインやUIの部分は、想定する使い方が変わると、
「使いやすさ」を実現する方法も変わってしまいます。
これらの全て実装すると開発期間やコストをオーバーしてしまいますので、
まずは普通の使い方で不便を感じない実装が重要だと考えています。

それでも「期待以上だった」とお客様に言って頂けるような、
そんなソフトウェアを目指しています。

C# のコーディング規則

C# のコーディング規則
Microsoft公式ドキュメントに「C# のコーディング規則」が追加されました。
2021/5/14 の新しい内容です。

この記事のガイドラインは、サンプルおよびドキュメントを開発するために Microsoft によって使用されます。これらは、.NET ランタイムの C# コーディング スタイル ガイドラインから採用されました。それらを使用することも、ニーズに合わせて調整することもできます。 主な目的は、プロジェクト、チーム、組織、または会社のソース コード内での一貫性と読みやすさです。

とあるように、Microsoftでも使用される内容なので、
コーディング規則はこれをベースにするのが良さそうです。
フィールドはキャメルケースに_プレフィクスを付ける事が明文化されています。

  • private または internal のフィールドに名前を付ける場合は、キャメルケースを使用し、_を使用してプレフィックスを付けます。
  • ステートメント補完をサポートする IDE でこれらの名前付け規則に従う C# コードを編集するときは、「_」と入力すると、オブジェクト スコープのすべてのメンバーが表示されます。
  • なので自動実装ではないプロパティを使用する場合、
    バッキングフィールド名はプロパティ名の先頭を小文字にして_プレフィックスを付けたものになります。

    あと気になった点は、次のような点でしょうか。
    コメントは文章で書くようにという事ですね。

  • private または internal である static フィールドを使用する場合は、s_プレフィックスを使用し、スレッド静的には t_を使用します。
  • コメントのテキストはピリオドで終了します。
  • もちろん最初に書いてあるように、この規則はニーズに合わせて調整することもできますが、
    基本の規則として知っておくと良いと思います。

    PlantUML を試してみました。

    5月の連休を利用して、UML図の作成にPlantUMLを試してみました。
    VSCode + 拡張機能の流行りの組み合わせです。
    普段は別の専用ソフトを使っているので、
    テキストベースで図を作成するのは、個人的には初めてです。

    練習に社内の研修用ソフトのシーケンス図を作成してみると、
    予想以上に簡単に作成することができました。
    テキストベースなので要素の配置などレイアウトを考える必要もなく、
    シンプルに書きたい事を書くことができる印象です。

    ほんの些細な事でも考える事が少なくなると、
    やりたい事がよりはっきり見えてくるのを実感しました。
    プログラムのソースコードを書くときでも、
    スコープは狭くする、ネストを深くしない、メソッドは小さく分ける…など、
    余計な事を考える余地が少なくなるよう工夫したいと思います。

    読みやすいコード

    コードは理解しやすくなければならない。
    「リーダブルコード」にもそう書かれています。

    他の人が読みやすいかどうかというのはとても重要な事だと思います。
    適切な変数名やメソッド名は理解を助けますし、
    説明変数なども積極的に利用するようにしています。
    書き方ひとつとっても、
    例えば変数を宣言して anotherClass のみ遅延した初期化が必要な場合、

    var myClass = new MyClass();
    var yourClass = new YourClass();
    AnotherClass anotherClass;

    と書くよりは、

    var myClass = new MyClass();
    var yourClass = new YourClass();
    var anotherClass = default(AnotherClass);

    と書く方が、それぞれの変数の位置が揃っていて、
    読みやすいのではないでしょうか。
    気取らず、気の利いた美しいコードを目指したいと思います。

    C#9.0 record

    C#9.0でrecord型が追加されました。
    まだ実務では使用していませんが、
    今後C#でとても重要な機能になると思っています。

    最も活躍できるのが、DDDのValueObjectでしょうか。
    今まではそれらしい事をするには等値性を表現する為に、
    Equals()やGetHashCode()をoverrideする必要がありましたが、
    record型はコンパイラが自動で行ってくれます。

    そして定義がとても簡単に行えます。
    Microsoftの説明を引用すると、

    public record Person {
     public string LastName { get; }
     public string FirstName { get; }
     public Person(string first, string last) => (FirstName, LastName) = (first, last);
    }

    と同じことが、

    public record Person(string FirstName, string LastName) { }

    と書けます。とても簡潔ですね。