tag:crieit.net,2005:https://crieit.net/users/apashoni/feed あぱしょにの投稿 - Crieit Crieitでユーザーあぱしょにによる最近の投稿 2022-06-15T07:10:44+09:00 https://crieit.net/users/apashoni/feed tag:crieit.net,2005:PublicArticle/18224 2022-06-13T18:26:17+09:00 2022-06-15T07:10:44+09:00 https://crieit.net/posts/expression-bodied-method-void 【C#】戻り値がvoidなメソッドで、式形式メンバー+三項演算子を使う <p>できるのかな?と思って興味本位でなんやかんややってみたのでメモです。</p> <p>次のようなメソッドがあるとします。</p> <pre><code class="csharp">void DoSomething() { // 何らかの処理 } void DoSomethingIfNeeded(bool isNeeded) { if (isNeeded) DoSomething(); } </code></pre> <p>この時、<code>DoSomethingIfNeeded</code> をシンプルに式形式メンバーで書きたいと思いました。イメージとしてはこんな感じ。</p> <pre><code class="csharp">void DoSomethingIfNeeded(bool ifNeeded) => isNeeded ? DoSomething() : null; </code></pre> <p>上記コードはコンパイルが通りません。<code>void</code> なのに <code>null</code> を返しているからです。</p> <p>だったら処理のない <code>DoNothing</code> 的なメソッドを実行させれば良いのでは?と思い、次のように書いてみました。</p> <pre><code class="csharp">void DoNothing() { return; } void DoSomethingIfNeeded(bool isNeeded) { isNeeded ? DoSomething() : DoNothing(); } </code></pre> <p>しかしこれもコンパイルエラーになります。</p> <blockquote> <p>CS0201: 代入、呼び出し、インクリメント、デクリメント、新しいオブジェクトの式のみがステートメントとして使用できます</p> </blockquote> <p>なるほど…。それなら三項演算子には、どのメソッドを呼び出すかの判定だけをしてもらえばいいのでは?</p> <p>ということで下記のように書いてみました。</p> <pre><code class="csharp">void DoSomethingIfNeeded(bool isNeeded) => ( isNeeded ? DoSomething : DoNothing )(); </code></pre> <p>これなら、やっていることは <code>DoSomething</code> か <code>DoNothing</code> かだから通るでしょう、という魂胆です。しかしこれも通りません。</p> <blockquote> <p>CS0149: メソッド名が必要です</p> </blockquote> <p>そうですか…。</p> <p>いやいやおかしいでしょ、実行すべきメソッドを決定しているのに、メソッド名が必要なのは変では?と思い調べてみたところ、以下の記事にたどり着きました。</p> <p>僕はね、voidが戻りの関数を三項演算子みたいに使いたかっただけなんだ<br /> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/vranometria/items/cfe6f282d7973ae7f52b">https://qiita.com/vranometria/items/cfe6f282d7973ae7f52b</a></p> <p>キャスト…。どちらも <code>Action</code> であることは明らかだと思うのだけど、明示的なキャストが必要なのか…。何故…。</p> <p>キャストを入れてみます。</p> <pre><code class="csharp">void DoSomethingIfNeeded(bool isNeeded) => ( isNeeded ? (Action)DoSomething : DoNothing )(); </code></pre> <p>これでコンパイルが通りました。</p> <p>あとは、何もしない処理にわざわざ <code>DoNothing</code> という名前を付ける必要もないので匿名化します。</p> <pre><code class="csharp">void DoSomethingIfNeeded(bool isNeeded) => ( isNeeded ? (Action)DoSomething : () => { } )(); </code></pre> <p>これで一応、当初の目的は達成できました。<code>DoSomething</code> に簡単な処理を入れて実行してみます。</p> <pre><code class="csharp">void DoSomething() { Console.WriteLine("hoge"); Console.WriteLine("fuga"); } void DoSomethingIfNeeded(bool isNeeded) => ( isNeeded ? (Action)DoSomething : () => { } )(); DoSomethingIfNeeded(true); Console.WriteLine("piyo"); // hoge // fuga // piyo DoSomethingIfNeeded(false); Console.WriteLine("piyo") // piyo </code></pre> <p>できました。キャストが必要な理由は勉強が必要。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <p>僕はね、voidが戻りの関数を三項演算子みたいに使いたかっただけなんだ<br /> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/vranometria/items/cfe6f282d7973ae7f52b">https://qiita.com/vranometria/items/cfe6f282d7973ae7f52b</a></p> <p>Expression-bodied members (C# programming guide)<br /> <a target="_blank" rel="nofollow noopener" href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members">https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members</a></p> あぱしょに tag:crieit.net,2005:PublicArticle/18209 2022-06-06T18:50:19+09:00 2022-06-06T18:50:19+09:00 https://crieit.net/posts/wrap-linq-methods 【C#】LINQ のメソッド名が SQL っぽいからラップする <h2 id="SQL チックなメソッド名"><a href="#SQL+%E3%83%81%E3%83%83%E3%82%AF%E3%81%AA%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E5%90%8D">SQL チックなメソッド名</a></h2> <p>C# の <em>LINQ to Object</em>(以下、単に LINQ と記載) はとても便利なんですけど、メソッド名が SQL っぽくて、いまいち直感的ではない上にダサいです。例として、JavaScript と比較してみましょう。<br /> <div class="table-responsive"><table> <thead> <tr> <th>LINQ でのメソッド名</th> <th>JavaScript のメソッド名</th> </tr> </thead> <tbody> <tr> <td>Select</td> <td>map</td> </tr> <tr> <td>Where</td> <td>filter</td> </tr> <tr> <td>OrderBy</td> <td>sort</td> </tr> </tbody> </table></div></p> <p>以下は、実際に利用する例です。<br /> JavaScript ではこう。</p> <pre><code class="javascript">const hoge = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; const fuga = hoge.filter(x => x % 2 === 0).map(x => x * 2).sort(); </code></pre> <p>C# ではこう。</p> <pre><code class="csharp">var hoge = new[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; var fuga = hoge.Where(x => x % 2 == 0).Select(x => x * 2).OrderBy(x => x).ToArray(); </code></pre> <p>もちろん慣れてくれば <code>Select</code> だろうが <code>Where</code> だろうがスラスラ読めるのですが、慣れていなければ引っかかるかもしれません。一方、<code>map</code>, <code>filter</code>, <code>sort</code> というのは直感的で意味がわかりやすいです。</p> <h2 id="ラップする"><a href="#%E3%83%A9%E3%83%83%E3%83%97%E3%81%99%E3%82%8B">ラップする</a></h2> <p>ということで、ラッパーメソッドで名前を変えます。</p> <h3><code>Select</code> => <code>Map</code></h3> <pre><code class="csharp">public static IEnumerable<TResult> Map<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> func) => source.Select(x => func(x)); public static IEnumerable<TResult> Map<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> func) => source.Select((x, index) => func(x, index)); </code></pre> <h3><code>Where</code> => <code>Filter</code></h3> <pre><code class="csharp">public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Func<bool> func) => source.Where(x => func()); public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Func<T, bool> func) => source.Where(x => func(x)); public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, bool func) => source.Where(x => func); </code></pre> <h3><code>OrderBy</code> => <code>Sort</code></h3> <pre><code class="csharp">public static IOrderedEnumerable<TSource> Sort<TSource, TKey>(this IEnumerable<TSource> sources, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) => sources.OrderBy(keySelector, comparer); public static IOrderedEnumerable<TSource> Sort<TSource, TKey>(this IEnumerable<TSource> sources, Func<TSource, TKey> keySelector) => sources.OrderBy(keySelector); public static IOrderedEnumerable<TSource> SortByDesc<TSource, TKey>(this IEnumerable<TSource> sources, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) => sources.OrderByDescending(keySelector, comparer); public static IOrderedEnumerable<TSource> SortByDesc<TSource, TKey>(this IEnumerable<TSource> sources, Func<TSource, TKey> keySelector) => sources.OrderByDescending(keySelector); </code></pre> <p>ソートに関しては、元の <code>OrderBy</code> が、昇順か降順かでメソッドが別れています。昇順のソートが <code>OrderBy</code>、降順のソートが <code>OrderByDescending</code> なので、それぞれ <code>Sort</code>、 <code>SortByDesc</code> というメソッド名でラップしましたが、ここは昇順か降順かをオプション引数で切り替える <code>Sort</code> という名前のメソッドにしても良いでしょう。</p> <p>「昇順か降順かをメソッド名だけで判断できる」という利点はありますが、同じようなことが別の名前のメソッドで定義されているのも、個人的には気持ち悪いと感じます。</p> <p>同様に、<code>ThenBy</code> と <code>ThenByDescending</code> も <code>Then</code> というメソッドでラップしてみます。</p> <pre><code class="csharp">public static IOrderedEnumerable<TSource> Sort<TSource, TKey>(this IEnumerable<TSource> sources, Func<TSource, TKey> keySelector, IComparer<TKey> comparer, bool byDesc) => byDesc ? sources.OrderByDescending(keySelector, comparer) : sources.OrderBy(keySelector, comparer); public static IOrderedEnumerable<TSource> Sort<TSource, TKey>(this IEnumerable<TSource> sources, Func<TSource, TKey> keySelector, bool byDesc) => byDesc ? sources.OrderByDescending(keySelector) : sources.OrderBy(keySelector); public static IOrderedEnumerable<TSource> Then<TSource, TKey>(this IOrderedEnumerable<TSource> sources, Func<TSource, TKey> keySelector, IComparer<TKey> comparer, bool byDesc) => byDesc ? sources.ThenByDescending(keySelector, comparer) : sources.ThenBy(keySelector, comparer); public static IOrderedEnumerable<TSource> Then<TSource, TKey>(this IOrderedEnumerable<TSource> sources, Func<TSource, TKey> keySelector, bool byDesc) => byDesc ? sources.ThenByDescending(keySelector) : sources.ThenBy(keySelector); </code></pre> <p>オプション引数 <code>byDesc</code> を設定しました。これにより、次のようにコードを書けます。</p> <pre><code class="csharp">// ラップ前 var hoge = GetEmployee.OrderBy(s => s.Age).ThenByDesc(x => x.Salary); // ラップ後 var hoge = GetEmployee.Sort(s => s.Age).Then(s => s.Salary, byDesc: true); </code></pre> <p>もちろん引数名の <code>byDesc</code> を省略することもできますが、理由があり記載しています。理由については、以下の記事で解説しているので、よかったらご覧ください。</p> <p><a href="https://crieit.net/posts/dare-to-write-argument-names-patterns">【C#】あえて引数名を書くパターン</a></p> <h2 id="比較"><a href="#%E6%AF%94%E8%BC%83">比較</a></h2> <p>メソッド名をラップしてみることで、冒頭のコードは次のように書けるようになりました。</p> <pre><code class="csharp">// 変更前 var hoge = new[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; var fuga = hoge.Where(x => x % 2 == 0).Select(x => x * 2).OrderBy(x => x).ToArray(); // 変更後 var hoge = new[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; var fuga = hoge.Filter(x => x % 2 == 0).Map(x => x * 2).Sort(x => x).ToArray(); </code></pre> <p>LINQ にあまり慣れていない人でも、よりスッと入ってきやすいコードになったのではないでしょうか。</p> あぱしょに tag:crieit.net,2005:PublicArticle/18208 2022-06-02T19:00:09+09:00 2022-06-15T09:04:01+09:00 https://crieit.net/posts/dare-to-write-argument-names-patterns 【C#】あえて引数名を書くパターン <p>C# では、メソッドやコンストラクタに引数を渡す際に引数名を省略してコードを書く場合が多いと思いますが、明示的に引数名を書くこともできます。</p> <pre><code class="csharp">int Add(int x, int y) => x + y; // 引数名を省略する場合 var hoge = Add(10, 20); // 引数名を明記する場合 var fuga = Add(x: 10, y: 20); </code></pre> <p>省略しても問題ない引数名を、わざわざ明記するパターンは以下のような場合が考えられます。</p> <h2 id="メソッドで定義している引数の順番とは違う順番で書ける"><a href="#%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A7%E5%AE%9A%E7%BE%A9%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E5%BC%95%E6%95%B0%E3%81%AE%E9%A0%86%E7%95%AA%E3%81%A8%E3%81%AF%E9%81%95%E3%81%86%E9%A0%86%E7%95%AA%E3%81%A7%E6%9B%B8%E3%81%91%E3%82%8B">メソッドで定義している引数の順番とは違う順番で書ける</a></h2> <pre><code class="csharp">float Div(float x, float y) => x / y; // x と y をメソッド定義とは異なる順番で渡す Console.Write(Div(y: 2f, x: 1f)); // 0.5 </code></pre> <p>とはいえ、何か特別な意図がない限りこういった使い方はしないと思います。</p> <h2 id="複数の省略可能引数(オプション引数)のうち一つを明示的に指定する"><a href="#%E8%A4%87%E6%95%B0%E3%81%AE%E7%9C%81%E7%95%A5%E5%8F%AF%E8%83%BD%E5%BC%95%E6%95%B0%EF%BC%88%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E5%BC%95%E6%95%B0%EF%BC%89%E3%81%AE%E3%81%86%E3%81%A1%E4%B8%80%E3%81%A4%E3%82%92%E6%98%8E%E7%A4%BA%E7%9A%84%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B">複数の省略可能引数(オプション引数)のうち一つを明示的に指定する</a></h2> <pre><code class="csharp">void Demo(int x, bool isHoge = false, bool isFuga = false, bool isPiyo = false) { Console.WriteLine($"x: {x}"); Console.WriteLine($"isHoge: {isHoge}"); Console.WriteLine($"isFuga: {isFuga}"); Console.WriteLine($"isPiyo: {isPiyo}"); } // isHoge と isFuga はデフォルト値のまま、isPiyo のみ指定 Demo(10, isPiyo: true); // x: 10 // isHoge: False // isFuga: False // isPiyo: True // 名前付き引数を使用しない場合、すべての引数を明示的に指定する必要がある Demo(10, false, false, true); </code></pre> <p>これも、元々のメソッドの設計があまり良くないなどの理由で、後付けで省略可能引数がわんさか付いているようなメソッドというのは古いコードではよくあります。</p> <h2 id="可読性の向上;「この引数でどうなるんだっけ?」対策"><a href="#%E5%8F%AF%E8%AA%AD%E6%80%A7%E3%81%AE%E5%90%91%E4%B8%8A%EF%BC%9B%E3%80%8C%E3%81%93%E3%81%AE%E5%BC%95%E6%95%B0%E3%81%A7%E3%81%A9%E3%81%86%E3%81%AA%E3%82%8B%E3%82%93%E3%81%A0%E3%81%A3%E3%81%91%EF%BC%9F%E3%80%8D%E5%AF%BE%E7%AD%96">可読性の向上;「この引数でどうなるんだっけ?」対策</a></h2> <p>例として以下の <code>StreamWriter</code> の場合を考えてみます。</p> <pre><code class="csharp">var path = GetPath(); using (var sw = new StreamWriter(path, flase)) sw.Write("hoge"); </code></pre> <p><code>StreamWriter</code> のコンストラクタの第2引数に <code>false</code> を渡しています。この第2引数は <code>append</code> という引数名で定義されており、既にファイルが存在する場合に末尾に書き込むか、新しく上書きするかを真偽値で指定します<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。</p> <p>ところが数年ぶりに <code>StreamWriter</code> を使ってこのコードを見た場合、この <code>false</code> がどういう作用をもたらすのか<strong>瞬時に</strong>理解できるでしょうか?</p> <p>もちろん、IDE上で見る場合は引数の説明をいつでも参照することができます。そうでない場合でも、<a target="_blank" rel="nofollow noopener" href="https://referencesource.microsoft.com/">公式のリファレンスソース</a>を参照することができることでしょう。この <code>false</code> が何をもたらすかというのは、数十秒あれば解決できる疑問かもしれません。</p> <p>しかし、引数名を明記しておくと数十秒とかからず、<strong>コードを見ただけで瞬時に</strong>判断できるようになります。</p> <pre><code class="csharp">var path = GetPath(); using (var sw = new StreamWriter(path, append: flase)) sw.Write("hoge"); </code></pre> <p>「この <code>false</code> の引数名、<code>append</code> ってことはこの場合追記じゃなくて上書きなのか」と、<strong>定義やドキュメントを参照するまでもなく</strong>コードを読んだ瞬間に意味を理解することができます。これはかなり大きなメリットなのではないでしょうか。</p> <p>さらに、今回は <code>StreamWriter</code> を例に出しましたが、もしこれが公式のライブラリではなく、ドキュメントもろくにメンテされていない独自ライブラリだとしたらどうでしょう。「そのような環境の方が問題だろ!」というのももっともですが、しかし全てのドキュメントのメンテが行き届いている環境ばかりではありません。</p> <p>個人的には、コメントに「falseは上書き」みたいなことを書くよりは、<code>append: false</code> と書いた方が余程良いと思います<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> <hr /> <p>以上、個人的に想定する「引数名を明示する理由」をまとめてみました。</p> <p>以下、おまけ。</p> <p>最後のコメント的な用法に関しては、自作クラスを使う場合は <code>WritingMode</code> みたいな <code>Enum</code> を受け取るようにして、</p> <pre><code class="csharp">using (var ow = OriginalWriter(path, WritingMode.Overwrite)) ow.Write("hoge"); // WritingMode は // WritingMode.Overwrite => 上書き // WritingMode.Append => 追記 </code></pre> <p>という形で受け取るようにすれば、引数名を書かずとも「<strong>この引数では書込みモードを指定してますよ</strong>」という意図が明確になることもあります。自作する場合は、たとえ真偽値で判断できる場合でもあえて <code>Enum</code> を併用して、より意図を込めやすくなるように工夫できれば良いと思います。</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p><strong>参考</strong> StreamWriter クラス|StreamWriter(String, Boolean)<br /> <a target="_blank" rel="nofollow noopener" href="https://docs.microsoft.com/ja-jp/dotnet/api/system.io.streamwriter?view=net-6.0">https://docs.microsoft.com/ja-jp/dotnet/api/system.io.streamwriter?view=net-6.0</a> <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:2" role="doc-endnote"> <p>コメントが悪という主張ではなく、<strong>コードで表現できることは、できるだけコードで表現すべき</strong>という主張です。たとえば「なぜ追記じゃなくて上書きをするのか」という意図が共有してあるのは良いコメントだと感じます。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> あぱしょに tag:crieit.net,2005:PublicArticle/17767 2021-11-17T20:22:26+09:00 2021-11-17T20:22:26+09:00 https://crieit.net/posts/if-expression-in-csharp 【C#】え!!C#でif式を?できらぁ! <p>タイトルは正確ではありません。すいません。if式っぽく書ける条件判定関数的なものです。if式っぽく書きたかったので作ってみました。</p> <p>C#の<code>if</code>は文であって式ではありません。式ではないので</p> <pre><code class="csharp">var name = "ほげほげ君"; // こうは書けない var exName1 = if (name.EndsWith("君")) { return name; } else { return name + "君"; } // こう書く var exName2 = ""; if (name.EndsWith("君")) exName = name; else exName2 = name + "君"; </code></pre> <p>みたいに書かなければいけません。人によるかと思いますが、これ読みにくくないですか?<code>exName2</code>への代入が2箇所あるので読んでて鬱陶しいです。何度もこういうコードが出てくると嫌です。</p> <p>このくらいのコードであれば三項演算子で解決するという方法もあるでしょう。</p> <pre><code class="csharp">var name = "ほげほげ君"; var newName = name.EndsWith("君") ? name : name + "君"; </code></pre> <p>これであれば代入は1箇所ですし分かりやすいですね。しかし、次のようなケースではどうでしょう。</p> <pre><code class="csharp">// 三項演算子 var newName = name.EndsWith("さん") ? Regex.Replace(name, "さん$", "君") : (name.EndsWith("君") ? name : name + "君"); // if文 var newName = ""; if (name.EndsWith("さん")) newName = Regex.Replace(name, "さん$", "君"); else if (name.EndsWith("君")) newName = name; else newName = name + "君"; </code></pre> <p>最後が"さん"であれば"君"に変換するという場合は、三項演算子を使えば分かりにくくなり、<code>if</code> <code>else if</code> <code>else</code>では悪戯に長くなりますし結局代入箇所が分散していますね。もっとこう、スパっと書けないものでしょうか。ということでif式っぽいものを作りました。</p> <pre><code class="csharp">// ex.1 var newName1 = Ext.If(name.EndsWith("さん"), Regex.Replace(name, "さん$", "君")) .ElseIf(!name.EndsWith("君"), name + "君") .Else(name); </code></pre> <p>あるいは</p> <pre><code class="csharp">// ex.2 var newName2 = name.EndsWith("さん").Then(Regex.Replace(name, "さん$", "君")) .ElseIf(!name.EndsWith("君"), name + "君") .Else(name); </code></pre> <p>上記のように書くためのメソッドです。条件に対して欲しい結果をメソッドチェーンで書いていけるのでなんとなく読みやすいと思います。</p> <p>まずは<strong>ex.1</strong>にある<code>If</code> <code>ElseIf</code> <code>Else</code>というメソッドがこちら。</p> <pre><code class="csharp">public static Tuple<bool, T> If<T>(bool term, T value) { if (term) { // 条件が成立する場合はvalue return new Tuple<bool, T>(true, value); } else { // 条件が成立しない場合はT型のdefault return new Tuple<bool, T>(false, default); } } public static Tuple<bool, T> ElseIf<T>(this Tuple<bool, T> prev, bool term, T value) { if (prev.Item1) { // 前の式が成立している場合はそれをそのまま返す return prev; } else if (term) { // 条件が成立する場合はvalue return new Tuple<bool, T>(true, value); } else { // 条件が成立しない場合はT型のdefault return new Tuple<bool, T>(false, default); } } public static T Else<T> Else(this Tuple<bool, T> prev, T value) { if (prev.Item1) { // 前の式が成立する場合は、その値を取り出して返す return prev.Item2; } else { // 前の式が成立しない場合は規定値としてvalueを返す return value; } } </code></pre> <p>if式を実現するにあたり、前の式の計算結果と値を受け取って引き継ぎつつ、最終的には値のみを返すという処理をする必要があります。そのため、<code>Tuple<bool, T></code>でそれらの情報を受け渡し、最終的に<code>Else</code>で<code>T</code>型の値部分のみを返しています。</p> <p><code>ElseIf</code>と<code>Else</code>では<code>Tuple<bool, T></code>の拡張メソッドを使用しています。なので、このメソッドは<code>static</code>なクラスで宣言する必要があります。</p> <p>続いて<strong>ex.2</strong>にある<code>Then</code>について。<strong>ex.2</strong>の<code>ElseIf</code>と<code>Else</code>は<strong>ex.1</strong>のものと同様です。</p> <pre><code class="csharp">public static Tuple<bool, T> Then<T>(this bool term, T value) { if (term) { // 条件が成立する場合はvalue return new Tuple<bool, T>(true, value); } else { // 条件が成立しない場合はT型のdefault return new Tuple<bool, T>(false, default); } } </code></pre> <p>これも単純に<strong>ex.1</strong>の<code>If</code>の引数<code>term</code>を、引数ではなくメソッドチェーン的に取れるように<code>this</code>キーワードで拡張したメソッドになります。<code>this</code>キーワードにしている引数は明示的に指定することも可能なので、なんなら<strong>ex.1</strong>の<code>If</code>メソッドをこの<code>Then</code>メソッドで代用することも可能です。(条件を指定するならIf的な名前がいいと思って別に定義しました)</p> <p><code>ElseIf</code>は必要に応じて省略することも、複数記述することもできます。</p> <pre><code class="csharp">var point = GetPoint(); var score = Ext.If(point == 100, "S") .ElseIf(point >= 80, "A") .ElseIf(point >= 60, "B") .ElseIf(point >= 40, "C") .ElseIf(point >= 30, "D") .Else("E"); </code></pre> <p>このように書けます。if文でちまちま書いたり三項演算子でネストして書いていくよりはるかにわかりやすいと思います。</p> <p><code>Func</code>や<code>Action</code>を受け取るよう拡張すれば、ラムダ式などを使ってより柔軟な表現が出来るようになると思います。たとえばActionだと、</p> <pre><code class="csharp">public static bool Then(this bool term, Action action) { if (!term) return false; action(); return true; } public static bool ElseIf(this bool previous, bool term, Action action) { if (previous) return true; else if (!term) return false; action(); return true; } public static void Else(this bool previous, Action action) { if (previous) return; action(); } // *** var point = GetPoint(); (point == 100).Then(() => Console.WriteLine("S")) .ElseIf((point >= 80), () => Console.WriteLine("A")) .ElseIf((point >= 60), () => Console.WriteLine("B")) .ElseIf((point >= 40), () => Console.WriteLine("C")) .ElseIf((point >= 30), () => Console.WriteLine("D")) .Else(() => Console.WriteLine("E")); </code></pre> <p>こんな感じで書けます。</p> <p>ジェネリクスを使用していますが制約などはつけていませんし、より最適なコードもあるかもしれません。ある程度拡張性はあると思いますが、もっといいやり方あるよ!などがあれば、是非教えてください。</p> あぱしょに tag:crieit.net,2005:PublicArticle/17728 2021-10-28T20:25:58+09:00 2021-10-28T22:44:12+09:00 https://crieit.net/posts/use-shortcut-commands-to-open-frequently-used-directories よく使うディレクトリはショートカットコマンドで開こう <p><img src="https://img.shields.io/badge/-Windows-0078D6.svg?logo=windows&style=flat" alt="OS:Windows" /></p> <p>今回のは簡単に準備できて恩恵の大きい時短テクです。</p> <p>ITエンジニア以外の方でも、たとえば頻繁にPC内の特定のディレクトリ(≒フォルダ)を開いてその中のファイルを開く、という方は参考にしていただけるかと思います。</p> <p>たとえば、趣味でイラストを描いているAさんは、イラストのデータを<code>D:\作業\イラスト\制作中</code>というディレクトリに保存しているとします。イラストを描くために毎日このフォルダを開いているとしましょう。</p> <p>普通に開くなら、まずはタスクバーからエクスプローラーをクリックして、Dドライブをクリックして、作業、イラスト、制作中とマウスをポチポチと潜っていきますよね。あるいは、キーボード操作に慣れていてショートカットを覚えている人であれば<code>Windows</code>+<code>E</code>、<code>Alt</code>+<code>D</code>、そしてパスの入力をしていくかもしれません。</p> <p>でもこれすら面倒なんですよね。もっと良い方法があります。それはバッチファイルに落とし込んで、ショートカットコマンドで開く方法です。これをすれば一瞬で目的のフォルダを開くことができます。PCに詳しくない人でも簡単に設定できると思います。</p> <p><img src="https://img.shields.io/badge/-sei.bat-gray" alt="sei.bat" /></p> <pre><code class="bat">@echo off start "" "D:\作業\イラスト\制作中" </code></pre> <p>上記のようなバッチファイルを作成し、パスを通しておきます。</p> <p>バッチファイルの作成とパスを通す方法は<a href="https://crieit.net/posts/easy-hack-to-copy-date-yyyymmdd">【Windows】日付8桁(yyyymmdd)を簡単にクリップボードに入れる方法</a>という記事で詳しく解説しているので、そちらを参照してください。</p> <p>今回は、制作中というディレクトリを開きたいので<code>sei.bat</code>という名前で保存してみます。これでパスを通すと、<code>Windows</code>を押して<code>sei</code>を入力すると<code>D:\作業\イラスト\制作中</code>のディレクトリを開くことができます。</p> <p>ファイルの名前はなんでもいいですが、既にあるファイルと被らないように、かつ覚えやすくタイプするのも面倒ではないシンプルな名前が良いと思います。</p> <p>これを使えば、</p> <blockquote> <p><strong>たかし君</strong>「カモフラージュのために、保存先を<code>D:\勉強\社会\宿題\2021\202110\穴埋め問題\解答\答え合わせ\秘密\危険\閲覧注意\閲覧禁止\見るな!!!\エロ</code>にしたけど、開くまでが面倒だなあ・・・」</p> <p><strong>たかし君</strong>「かえって不便だし、これじゃあ意味ないよ・・・」</p> </blockquote> <p>といった時にも、一発で目的のブツを開くコマンドさえ用意すれば完璧です。どれだけ長くて複雑なパスでも問題なしです。やったねたかし君!もっとがんばれ。超がんばれ。</p> <p>コマンドファイルにするメリットは他にも、複数のコマンドをまとめて実行できるという点が挙げられます。たとえば、</p> <ol> <li>イラストのデータを保存している<code>D:\作業\イラスト\制作中</code>を開く</li> <li>資料用にダウンロードしたファイルを保存している<code>D:\作業\イラスト\資料</code>を開く</li> <li>資料を探したいから<a target="_blank" rel="nofollow noopener" href="https://www.pinterest.jp">Pinterest</a>と<a target="_blank" rel="nofollow noopener" href="https://pixiv.net">Pixiv</a>をChromeで、それぞれ別のウィンドウで開いておく</li> </ol> <p>こういう一連の動作をしたい場合でも、そういう命令を書けばコマンド一発で実行できます。</p> <p><img src="https://img.shields.io/badge/-sei.bat-gray" alt="sei.bat" /></p> <pre><code class="bat">@echo off start "" "D:\作業\イラスト\制作中" start "" "D:\作業\イラスト\資料" start chrome --new-window "https://www.pinterest.jp" start chrome --new-window "https://pixiv.net" </code></pre> <p>もし長期的に作業をするファイルがあるなら、それを直接開くように指定しても良いでしょう。とにかく使い方次第でかなり時短ができます。PC起動時に自動で実行するように設定しておけば、完全に自動化できます。</p> <p>また、半角入力と思ったら全角入力になってた場合などは<code>Windows</code> <code>sei</code>のつもりが<code>Windows</code> <code>せい</code>になったりします。その場合は<code>せい</code>を削除して改めて<code>sei</code>を入力する必要がありますが、その場合備えて<code>sei.bat</code>を実行する<code>せい.bat</code>というファイルを作っておくと、いちいち再入力する手間が省けてストレスを減らせるのでオススメです。</p> <p><img src="https://img.shields.io/badge/-せい.bat-gray" alt="sei.bat" /></p> <pre><code class="bat">@echo off start cmd /c sei.bat </code></pre> <p><code>/c</code>オプションは、実行後にコマンドプロンプトを終了するというオプションです。これがないと、<code>せい.bat</code>経由で<code>sei.bat</code>を実行した時にコマンドプロンプトが残ったままになってしまうので入れておきます。</p> <p>たとえば私は<code>devdir.bat</code>で開発環境を展開するようにしていますが、対応する<code>でvぢr.bat</code>を作っています。これを用意しておけば、作業を始める時に<code>Windows</code>を押して<code>d</code> <code>e</code> <code>v</code> <code>d</code>あたりまで入力すればバッチファイルの候補を挙げてくれるので<code>Enter</code>を押すだけで良くなります。半角モードだろうが全角モードだろうが、問題なく作業の準備ができてとても良いです。</p> <p>他にも自動で作業中のファイルのバックアップを作ったりと、アレンジ次第で色々なことができます。興味があれば「Windows コマンド」などでググってみてください。</p> あぱしょに tag:crieit.net,2005:PublicArticle/17724 2021-10-26T20:31:27+09:00 2021-10-26T20:31:27+09:00 https://crieit.net/posts/about-curly-braces-of-if-statement-in-csharp C#のif文の波括弧{}について <p>C#では<code>if</code>などの<code>{}</code>を省略<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>して書けます。たとえば</p> <pre><code class="csharp">// これを if (girl.IsBoyish) { Console.Write("かわいいね"); } // こう if (girl.IsBoyish) Console.Write("かわいいね"); </code></pre> <p>こんな感じで書ける訳ですね。タイプ量が減りますし個人的にはこのスタイルが好きです。</p> <p>ただしあくまで<code>if</code>の後が単一の処理の場合なので、<code>girl.IsBoyish</code>が<code>true</code>の場合は「(1)コンソール出力」と「(2)ボーイッシュリストに入れる」ということをしたい場合に</p> <pre><code class="csharp">if (girl.IsBoyish) Console.Write("かわいいね"); boyishGirls.Add(girl); </code></pre> <p>こういう風には書けません。C#はインデントをブロックとして解釈しないので、このコードは下記の様に解釈されます。</p> <pre><code class="csharp">if (girl.IsBoyish) { Console.Write("かわいいね"); } boyishGirls.Add(girl); </code></pre> <p>この場合、「(1)コンソール出力」は<code>girl.IsBoyish</code>が<code>true</code>の場合のみですが、「(2)ボーイッシュリストに入れる」は<code>girl.IsBoyish</code>が<code>false</code>でも実行されてしまいます。</p> <p>ボーイッシュリストにボーイッシュじゃない女の子が入っていると都合が悪いですよね?ね?</p> <p>なので、正しくは</p> <pre><code class="csharp">if (girl.IsBoyish) { Console.Write("かわいいね"); boyishGirls.Add(girl); } </code></pre> <p>と書かなければなりません。</p> <p>※実際には<code>if</code>の<code>{}</code>を省略して複数行書くと、<code>boyishGirls.Add(girl);</code>の行のインデントはIDEなどでは効かないので、<code>if</code>の範囲外ということはすぐに分かると思います。</p> <p>こういう事情があるので、<code>if</code>と<code>else</code>が連続するような判定では<code>{}</code>を省略すると意図しない結果になる場合があります。たとえば次のようなケースをプログラムで表現するとします。</p> <pre><code class="csharp">if (!girl.HasShortHair) { if (girl.IsBokuGirl) { Console.Write("かわいいね"); } } else { Console.Write("かわいいね"); } </code></pre> <p>上記は「女の子がショートヘアでなく、かつボクっ娘である」または「女の子がショートヘアである」場合にコンソール出力をするというコードです。</p> <p>※この条件判定は私の趣味ですが「ショートヘアでもボクっ娘でもない女の子は可愛くねぇ!」という主張ではありませんのでご承知おきください。</p> <p>これを、<code>{}</code>を省略しようと思って下記のように書くとします。</p> <pre><code class="csharp">if (!girl.HasShortHair) if (girl.IsBokuGirl) Console.Write("かわいいね"); else Console.Write("かわいいね"); </code></pre> <p>一見<code>{}</code>を省けたように見えますが、前述の通りC#ではインデントはブロックとして解釈されません。つまり、上記のコードは下記のように解釈されます。</p> <pre><code class="csharp">if (!girl.HasShortHair) { if (girl.IsBokuGirl) { Console.Write("かわいいね"); } else { Console.Write("かわいいね"); } } </code></pre> <p>するとどうでしょう、「女の子がショートヘアでない場合、ボクっ娘であればコンソール出力、ボクっ娘でなくてもコンソール出力」「女の子がショートヘアの場合は何もしない」というコードになってしまいました。意図が真逆になっています。</p> <p>なので、こういうケースでは<code>{}</code>を使って<code>else</code>がどの<code>if</code>に対応しているものなのかを明示的に記載する必要があります。</p> <pre><code class="csharp">if (!girl.HasShortHair) { if (girl.IsBokuGirl) Console.Write("かわいいね"); } else Console.Write("かわいいね"); </code></pre> <p>上記のようにすれば問題なく、本来の要件を満たす条件判定となります。個人的な好みとしては<code>if</code>に<code>{}</code>を付けるなら<code>else</code>にも<code>{}</code>を(単一処理でも)付けたいです。</p> <p><code>if</code>の<code>{}</code>を省略する場合は、シンプルな処理であればタイプ量も減りシンプルで見通しの良いコードになりますが、複数条件が入り組んだ式の場合は注意が必要です。</p> <p>※説明のために意図的に分かりにくく書きましたが、上記の例であれば</p> <pre><code class="csharp">if (girl.HasShortHair || girl.IsBokuGirl) Console.Write("かわいいね"); </code></pre> <p>のようにロジックを見直して吸収できたりもするので、柔軟に考えてみると良いと思います。</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>C#の歴史的背景に詳しくないのですが、「もともと<code>if</code>はそれに続く単一の処理をするのであり、<code>{}</code>で複数の処理を単一の処理っぽくしているのであって、省略とかではなく本来<code>{}</code>がないのが成り立ち的には正しいのである」とか…。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> あぱしょに tag:crieit.net,2005:PublicArticle/17599 2021-08-14T13:55:16+09:00 2021-08-14T13:55:16+09:00 https://crieit.net/posts/how-to-restore-colors-of-web-twitter WEB版Twitterの色を元に戻すぞ <p>Twitterの仕様がまた変更されました。個人的には頻繁に仕様を変えて色々とっかえひっかえ試していき、より良いものを追求するという姿勢自体には賛成ですが、今回の仕様変更はちょっと困るなあ、という感じです。</p> <p>今回の仕様変更は配色の変更です。これはとても困ります。特に白と黒逆やろ!と思います。絶対間違えて誤フォローや誤フォロー解除が発生しまくるでしょう。なので、私の環境ではWEB版だけでも戻します。内容としては<a target="_blank" rel="nofollow noopener" href="https://boyi.sh/2021/04/18/hide-trends-and-topics-on-web-twitter/">WEB版Twitterのトレンドとかトピックを非表示にする</a>と同じようなことをします。</p> <p>使うのは<a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha?hl=ja">Stylebot</a>という拡張機能。分かる人向けに書くと、サイトごとに独自のCSSを記述して上書きして見た目を好きなように変更したり、見たくない要素を非表示にしたりできるというものです。</p> <p>Chromeの拡張機能ですが、対応するブラウザで使えます。私の場合はBraveというブラウザでも問題なく使用できています。Braveに関して興味があれば<a target="_blank" rel="nofollow noopener" href="https://boyi.sh/2021/06/02/changed-my-main-browser-from-chrome-to-brave/">メインブラウザをChromeからBraveに変えた話</a>をご覧ください。</p> <p>Stylebotで以下のコードを貼り付けてください。色は好みに合わせて自由にカスタマイズできます。詳しくはHTMLカラーコードなどでググってください。</p> <pre><code class="css">/* フォロー中の背景色 */ div.css-18t94o4.css-1dbjc4n.r-1niwhzg.r-1ccsd61.r-sdzlij.r-1phboty.r-rs99b7.r-15ysp7h.r-4wgw6l.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr { background-color: #09f; } /* 保存の背景色 */ div.css-18t94o4.css-1dbjc4n.r-14lw9ot.r-42olwf.r-sdzlij.r-1phboty.r-rs99b7.r-16y2uox.r-6gpygo.r-1b7u577.r-peo1c.r-1ps3wis.r-1ny4l3l.r-1udh08x.r-1guathk.r-1udbk01.r-o7ynqc.r-6416eg.r-lrvibr.r-3s2u2q.r-1glkqn6 { background-color: #09f; } /* 保存の文字色 */ div.css-18t94o4.css-1dbjc4n.r-14lw9ot.r-42olwf.r-sdzlij.r-1phboty.r-rs99b7.r-16y2uox.r-6gpygo.r-1b7u577.r-peo1c.r-1ps3wis.r-1ny4l3l.r-1udh08x.r-1guathk.r-1udbk01.r-o7ynqc.r-6416eg.r-lrvibr.r-3s2u2q.r-1glkqn6 div { color: white } /* 未フォローの背景色 */ div.css-18t94o4.css-1dbjc4n.r-14lw9ot.r-42olwf.r-sdzlij.r-1phboty.r-rs99b7.r-15ysp7h.r-4wgw6l.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr { background-color: transparent; border: solid 2px white; } /* 未フォローの文字色 */ div.css-18t94o4.css-1dbjc4n.r-14lw9ot.r-42olwf.r-sdzlij.r-1phboty.r-rs99b7.r-15ysp7h.r-4wgw6l.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr div{ color: white; } </code></pre> <p>今回行ったのは、開発者モードで該当の要素を見つけ出してStylebotで設定の付与です。Stylebotでも要素選択は可能なのですが、開発者モードで行った方が小回りがきいてやりやすいです。</p> <p>本来は共通クラスのみ抜き出して少ない記述でやりたかったのですが、あまりにも面倒くさくてベタ書きしました。</p> <p>上記コードはTwiterの仕様変更で無効になる可能性がありますが、その時はまた同じことをすればいいです。</p> <p>それでは素敵なTwitterライフを!</p> あぱしょに tag:crieit.net,2005:PublicArticle/17352 2021-06-02T20:16:27+09:00 2021-06-03T20:43:54+09:00 https://crieit.net/posts/changed-my-main-browser-from-chrome-to-brave メインブラウザをChromeからBraveに変えた話 <p>メインで使用しているブラウザを、Google ChromeからBraveに変えました。Braveは高品質な割にはそこまで普及していない気がします。せっかくなので紹介してみようと思います。</p> <h1 id="Braveについて"><a href="#Brave%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">Braveについて</a></h1> <p>BraveはjavaScriptの開発者であるBrendan Eich氏らが開発したブラウザで、無料で利用できます。次のような特徴があります。</p> <ul> <li>Windows/macOS/Linux/Android/iOSで利用可能</li> <li>標準で広告を非表示にする</li> <li>広告非表示にともなって読み込むデータ量が減り高速化する</li> <li>Braveが提供する広告を見ることでリワードを得るプログラムがある</li> </ul> <p>macOSはIntel/M1両対応しているそうです。あとは、他のブラウザもだいたいそうだと思いますが、Chromeの拡張機能がほとんど使えるのと、他のブラウザから閲覧履歴やブックマーク、認証情報などのインポートができます。</p> <p>Braveは標準でサードーパーティーCookie(以下TPC)をブロックします。TPCとは閲覧しているウェブサイト以外とやりとりするCookieのことで、たとえばこのブログでも表示しているGoogle AdSenseなどがあります。他にはYouTubeの動画に挿入される広告もTPCなので、<strong>Braveを利用すればYouTube Premiumのメンバーでなくても広告なしでYouTubeの動画を視聴できます</strong>。</p> <h1 id="なぜBraveを使おうと思ったか"><a href="#%E3%81%AA%E3%81%9CBrave%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86%E3%81%A8%E6%80%9D%E3%81%A3%E3%81%9F%E3%81%8B">なぜBraveを使おうと思ったか</a></h1> <p>実は私がBraveを利用するきっかけになったのも、この広告が標準で非表示になるという機能です。私はYouTube Premiumに加入しており、特典としてYouTube Musicも利用できますが、YouTube Musicがいつまで経っても使いにくいというかGooglePlay Musicの下位互換のような感じがしていました。一方Apple Musicは以前利用していた時はPC版のアプリケーション以外に特に不満はなく、<a target="_blank" rel="nofollow noopener" href="https://www.apple.com/jp/apple-one/">Apple One</a>というApple MusicとiCloud 50GBとその他特典がセットになってで月額1100円のサービスを利用しようと思っていました。実は、iCloud 50GB自体は契約していて、それが月130円かかっています。</p> <p>YouTube Premiumは月額1180円、それに加えてiCloud 50GBが月額130円で、合計毎月1310円支払っていることになりますが、Apple Oneにして、YouTubeの広告をBraveで非表示すれば1100円に抑えることができます。毎月210円浮かせることが出来る訳ですね。210円といってもバカにはできません。仮にあと500年生きるとして、毎月210円圧縮できればトータルで126万円も圧縮できますから。126万円ってすごいですよ。</p> <p>ただ、いくらBraveによるYouTubeの広告非表示が合法とはいえ、YouTubeが提供していない方法で広告を非表示にして一方的に得するのはちょっと私のポリシーに反するので、<a target="_blank" rel="nofollow noopener" href="https://one.google.com/about/plans?hl=ja">Google One</a>も利用して、Googleドライブを100GBに設定しようと思います。Googleドライブは無料枠で15GBの容量が提供されている太っ腹なサービスですが、私の用途だと15GBは少なすぎます。常々アップグレードしようと思っていたので、良い機会ですし100GBで契約しようと思います。ちなみにGoogleドライブの100GBプランは月額250円、年間プランだと2500円となり2カ月分お得になります。</p> <h1 id="導入方法"><a href="#%E5%B0%8E%E5%85%A5%E6%96%B9%E6%B3%95">導入方法</a></h1> <p>Windowsの場合はインストーラをダウンロードしてインストールする他、Chocolateyでもパッケージが配布されています。Chocoユーザーはそちらからインストールするのが楽でしょう。</p> <pre><code class="cmd">cinst brave -y </code></pre> <p>macOSではHomebrewで導入できます。</p> <pre><code class="cmd">brew install --cask brave-browser </code></pre> <p>iOS、AndroidはそれぞれApp Store/GooglePlayよりインストールできます。</p> <p>私の場合はChromeからブックマークと拡張機能をインポートしました。認証関係は1Passwordで管理しているのでインポートしませんでしたが、ブラウザからインポートすることができます。その他、閲覧履歴もインポートすることができます。</p> <p>あとは好みに応じて新しいタブの設定やテーマ・言語などを設定してください。これも特に説明は不要で、直感的に操作できると思います。</p> <h1 id="拡張機能"><a href="#%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD">拡張機能</a></h1> <p>使用している拡張機能は少ない方なので参考になるかはわかりませんが、Chromeで使用していた以下の拡張機能は使えました。</p> <ul> <li>Px Downloader</li> <li>uBlacklist</li> <li>Stylebot</li> </ul> <p>注意点として、拡張機能自体のインポートはできますが、それぞれの設定はできません。たとえばuBlacklistであればブロックするルールなどは再度設定する必要があります。まぁ昔のブラウザからコピペするだけでいいのですが。</p> <p>余談ですがuBlacklistはブラックリスト系の拡張機能としてはとても使いやすいのでオススメです。ドメイン単位や、細かい正規表現を設定して検索結果から排除することができます。私は主にいかがでしたかブログなど低品質なサイトをブロックしています。</p> <h1 id="その他"><a href="#%E3%81%9D%E3%81%AE%E4%BB%96">その他</a></h1> <p>初めにさらっと紹介しましたがBraveには、Braveが提供する広告を見ることによってBATというポイント(仮想通貨)を得て、それを特定のサイトにチップとして送ったり、自分自身がリワードとして受け取ることができます。</p> <p>この機能を有効にすると、一部のサイトではチップを送るという表示がでるようになります。たとえば、Twitterなどにも表示されます。</p> <p><a href="https://crieit.now.sh/upload_images/65effe08f1a79b8612a3b12b55d32f4d60b76842dc913.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/65effe08f1a79b8612a3b12b55d32f4d60b76842dc913.jpg?mw=700" alt="001" /></a></p> <p>この一番右のアイコンが、Twitterとは関係ないBrave独自の「チップを送る」ボタンです。普段は煩わしいので非表示にする方法を紹介します。</p> <p>まず拡張機能のStylebotを開きます。インストールしていない人はインストールしてください。</p> <p><a href="https://crieit.now.sh/upload_images/cd98267a2f4eaad828b5094c23951f4860b76850330f6.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/cd98267a2f4eaad828b5094c23951f4860b76850330f6.jpg?mw=700" alt="002" /></a></p> <p>左上の矢印をクリックし、Twitter上のチップのアイコンを選択します。</p> <p><a href="https://crieit.now.sh/upload_images/363a77cfcbdd967c9a726185ca7380c660b7685dd8ae3.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/363a77cfcbdd967c9a726185ca7380c660b7685dd8ae3.jpg?mw=700" alt="003" /></a></p> <p>Stylebotで「隠す」をクリックすると、非表示にすることができます。</p> <p>面倒な人は、Stylebotに以下のコードをコピペしてください。</p> <pre><code class="css">div.ProfileTweet-action.js-tooltip.action-brave-tip { display: none; } </code></pre> <p>ただし、これらの設定は今後Braveの仕様変更により適用されなくなる可能性があります。万が一再びチップのアイコンが出てきた場合は、同様の手順で非表示にすることができます。</p> <h1 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h1> <p>実はBraveの存在は結構前から知っていたのですが、肉体的にも精神的にも余裕がなく導入を先延ばしにしていました。もっと早く使ってみても良かったと思います。一時期周囲の猛プッシュでVivaldiを使っていたのですが、Vivaldiは個人的にはあまり使い勝手が良くなかったです。なんかおせっかいな機能もあったりして。たとえばプライベートモードでTwitterにアクセスしたら、保存してあるアカウント情報でログインしますか?と聞いてきたり…。ログイン状態で見たくないからPrivateにしとるんやろがい、という…。</p> <p>Vivaldiも私に合わないというだけで素晴らしいブラウザなのだろうとは思いますが、Braveは私の用途を完璧にカバーしてくれており、今のところ「なんでこうなってんの?」的なのがないです。めっちゃいいですね。まぁ使用し始めて日が浅いからというのもあるかもですが…。</p> <p>私のブログ(boyi.sh)にもGoogle AdSenseを利用しており、Braveを使うと標準の設定ではブログ上の広告が排除されるのでまぁあまり紹介したくはないのですが、このブログに関しては別に広告目当てでガッポリ稼ぐぜ!といったブログではないので別にいいです。</p> <p>将来的にはboyi.shもBraveのクリエーターとして認証してもらい、チップを受け取れるようななればな~とのんびりとのんきに考えているので、その際にはチップを送っていただけるとありがたいです!</p> あぱしょに tag:crieit.net,2005:PublicArticle/17099 2021-05-12T21:20:27+09:00 2021-05-12T21:20:27+09:00 https://crieit.net/posts/regist-or-register 【プログラミング全般】「登録する」の意でregistと書くことの是非について <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p>「登録する」という意味でregistと書くのがあるあるなのかは分かりませんが、色んなプロジェクトで色んな人が書いたコードを見ても、結構registが使われていました。</p> <p>英語的には誤りであり、registという単語は存在しません。正しくはregisterです。ではなぜregisterではなくregistが使われているのか、そう書いた人ひとりひとりを捕まえて「あなたはなぜregiterではなくregistと書いたのですか?」とインタビューすることはできないので、勝手に推測しています。</p> <h1 id="registerではなくregistを使う理由を推測"><a href="#register%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8Fregist%E3%82%92%E4%BD%BF%E3%81%86%E7%90%86%E7%94%B1%E3%82%92%E6%8E%A8%E6%B8%AC">registerではなくregistを使う理由を推測</a></h1> <h2 id="-erが動詞っぽくないから"><a href="#-er%E3%81%8C%E5%8B%95%E8%A9%9E%E3%81%A3%E3%81%BD%E3%81%8F%E3%81%AA%E3%81%84%E3%81%8B%E3%82%89">-erが動詞っぽくないから</a></h2> <p>個人的には一番それっぽい理由だと思います。</p> <p>registerはまぎれもなく動詞なのですが、-erという接尾辞が「~する人」ということを表すので、-erを抜いたregistが「登録する」ということなのだろう、と思ったのではないかということですね。まぁ分からなくはないですが、辞書引こうよ…とは思いますね。</p> <h2 id="慣習になっているから"><a href="#%E6%85%A3%E7%BF%92%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%89">慣習になっているから</a></h2> <p>自分たちが手をつける以前のソースコードでびっしりとregistが使われており、registerを使いたいけど統一感なくなるのも気持ち悪いので、いやいやregistを使っているパターンですね。</p> <h2 id="短い方がいいから"><a href="#%E7%9F%AD%E3%81%84%E6%96%B9%E3%81%8C%E3%81%84%E3%81%84%E3%81%8B%E3%82%89">短い方がいいから</a></h2> <p>registerという語であることは知っているけど、registの方が短いしチーム内で意味も伝わるからregistにしているパターン。これもなくはないでしょうし、ベテランエンジニアがこんな感じで書いてたら他のメンバーも合わせざるを得ないみたいな感じになりそうです。</p> <p>insert→ins、update→updみたいに省略してもある程度意味が伝わるので、わざわざregisterと書く必要はないじゃんという発想かもしれません。</p> <p>おそらく上記のような理由があるのではないかと思います。</p> <h1 id="ググってみる"><a href="#%E3%82%B0%E3%82%B0%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">ググってみる</a></h1> <p>「登録する regist プログラマ」みたいなキーワードでググってみたところ、以下の記事がヒットしました。</p> <p><a target="_blank" rel="nofollow noopener" href="http://yanok.net/2010/08/-regist.html">「登録する」の罠: registは間違い、アクセントにも注意</a></p> <blockquote> <p>registerではなんとなく動詞らしく見えないので、こういう勘違いが発生してしまうのでしょう。</p> </blockquote> <p>「動詞っぽくないから説」を提唱されています。私もそう思います。ちょっとややこしい単語ではありますよね。</p> <p>この記事へ反応する形で、次のような記事もありました。</p> <p><a target="_blank" rel="nofollow noopener" href="http://talkingnonsense.coolk2.com/?p=303">正確さよりも意図が“素早く正確に伝わる”ことが重要 - 2011年09月05日</a></p> <blockquote> <p>プログラマやSEにとって、この単語が正しい英語かなんてどうでもいいことだ。さらに発音なんてさらにどうでもいいことだ。重要なことは、この単語を見た人間(おそらく同じプログラマかSEか)が、この単語が付いた機能なりファイルなりの概要を名前から安易にかつ正確に想像できるか?という点にある。</p> </blockquote> <p>これに関しては半分同意といいう感じです。発音に関しては個人的にはどうでもいいと思います。それは私の周りにもネイティブの英語話者がいないからかもしれないですが、コードレビューしていて「このトライアップロードメソッドは何をしているの?」みたいにカタカナ英語で言いますし双方通じています。</p> <p>ネーミングから容易に処理が分かるかというのも大事な視点です。</p> <blockquote> <p>たとえば、認証という単語はrecognitionやcertificationを使うのが妥当だと思われる。しかしrecognitionやcertificationという単語はあまり馴染みが無い。意味を調べるのに辞書を要する人間も多いだろう。さらに文字数も多すぎる。それを考慮して、俺は認証をする機能にはauthという略語(造語?)を良く使う。</p> </blockquote> <p>これに関しても同意できます。一方、英語の細かいニュアンスの違いを命名に落とし込んであると、より良いコードだなと思うこともあります。たとえば</p> <ul> <li>beginとstartの違い</li> <li>deleteとremoveの違い</li> <li>sinceとfromの違い</li> </ul> <p>などがコードリーディングを助けることもあるでしょう。</p> <p>例として挙げられているものでも、たとえばrecognitionだと「一度認識しているものを改めて認識する」ようなニュアンスの認証ですし(接頭辞re-が付いていますね)、certificationだと「何かを申請して、それが他の誰かに承認される」ようなニュアンスの認証、auth(authentication)だとIDとパスワードを使って認証(本人確認)するようなニュアンスの認証です<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。これらのニュアンスの違いがあるのに、認証は全部authでいいや!というのはちょっとどうかと個人的には思います。</p> <h1 id="英語はやっぱり大事"><a href="#%E8%8B%B1%E8%AA%9E%E3%81%AF%E3%82%84%E3%81%A3%E3%81%B1%E3%82%8A%E5%A4%A7%E4%BA%8B">英語はやっぱり大事</a></h1> <p>そういう意味では、「正しい英語」というのはニュアンスの違いなどの理解が及ぶ範囲であれば、それは重要だと個人的には思います。ただ、registとregisterに関してはニュアンスの違いとかではなくそもそも存在しない語と存在する語の違いなので、ここでは若干違う話題ではありますが。</p> <p>また、プログラミングはだいたい英語を使うため、正しい英語の重要性みたいなのを理解していないとトンチンカンなコードを書いたりします。一度directoryPassみたいな変数を見たことがあります(おそらく書きたかったのはdirectoryPath)。pathは結構頻出基礎的な単語だと思うのですが、自分より何年も長くコードを書いているような人が間違えていると、ある程度正しい英語を使うクセ付けというか、そういうのは大事だよなぁとも思います。少なくとも分からなかったらググる、あまりにも長くなりそうだったらローマ字で書くとかが「正確に伝わる」という意味ではアリだと思います。ローマ字の是非はまた議論が別れそうですが、個人的にはpathをpassと書かれるくらいならpasuと書いてもらった方が…いやpathくらい覚えてほしいな、やっぱ。</p> <p>個人的にはregistだろうがregisterだろうが意味は伝わるので、既にregistが使われているプロジェクトではregistを使います。でも自分が0から作るならregisterを使います。IDEの補完機能などを使えば2文字増えようが関係ないですし、逆に2文字をケチって「あれwこの人registっていう英単語はないって知らないのかな?ぷっぷくぷーw」と思われるくらいならしっかり書きます<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。まぁ思われても別にいいですけど。</p> <p>結局は環境次第ということだと思います。メリットデメリットあるので、ある程度クローズドな環境であればregistでもいいんじゃない?とは思いますね。ただ、世界中に公開するようなコードを書くのであればregisterを使っていた方が無難だとは思います。少し紹介しましたが、insert→ins、update→updで伝わるのになんでregistはダメなんだ!と思われたら、中途半端に略してて気持ち悪いからだと思います。中途半端にerだけ省略しても誰も幸せにならないのでregくらいまで省略すれないいんじゃないですかね?regだったら省略しているということが明かなので。registだと若干ひっかかるというか、気持ち悪い感は否めないです。個人的に。</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>私の理解が正しいかはわからないので鵜呑みにしないでくださいね。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:2" role="doc-endnote"> <p>私がregist派のみなさんをそのように思っているという訳ではないですよ。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> あぱしょに tag:crieit.net,2005:PublicArticle/17072 2021-05-08T22:36:30+09:00 2021-05-08T22:36:30+09:00 https://crieit.net/posts/switch-expression-in-csharp-8 C# 8.0のswitch式 <h1 id="switch式"><a href="#switch%E5%BC%8F">switch式</a></h1> <p>C#の<code>switch</code>が、C# 8.0から式で使えるようになってます。いいですね。</p> <p>良い例が思い浮かばないのが申し訳ないですが、このような<code>Enum</code>があるとします。</p> <pre><code class="csharp">public enum DayOfWeek { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, } </code></pre> <p>ある日付の曜日を日本語で表示するための<code>switch</code>を使用するとします。従来はこのように書いていました。</p> <pre><code class="csharp">var dow_eng = DateTime.Today.DayOfWeek; var dow_jpn = ""; switch ((DayOfWeek)dow_eng) { case DayOfWeek.Sunday: dow_jpn = "日曜日"; break; case DayOfWeek.Monday: dow_jpn = "月曜日"; break; case DayOfWeek.Tuesday: dow_jpn = "火曜日"; break; case DayOfWeek.Wednesday: dow_jpn = "水曜日"; break; case DayOfWeek.Thursday: dow_jpn = "木曜日"; break; case DayOfWeek.Friday: dow_jpn = "金曜日"; break; case DayOfWeek.Saturday: dow_jpn = "土曜日"; break; default: dow_jpn = "エラー"; break; } Console.Write(dow_jpn); </code></pre> <p>なっが~~。これいちいち<code>case</code>とか<code>default</code>とか<code>break</code>とかだらだらと書かなきゃいけなくて、すごく面倒ですよね。</p> <p>これがC# 8.0ではこう書けます。</p> <pre><code class="csharp">var dow_eng = DateTime.Today.DayOfWeek; var dow_jpn = (DayOfWeek)dow_eng switch { DayOfWeek.Sunday => "日曜日", DayOfWeek.Monday => "月曜日", DayOfWeek.Tuesday => "火曜日", DayOfWeek.Wednesday => "水曜日", DayOfWeek.Thursday => "木曜日", DayOfWeek.Friday => "金曜日", DayOfWeek.Saturday => "土曜日", _ => "エラー", }; Console.Write(dow_jpn); </code></pre> <p>すっきりしましたね。特徴としては<code>switch式</code>なので、それ自体が文字列を返してくれます。長ったらしく<code>case</code>とかを書かずに済むのはとても良いですね。</p> <p><code>default</code>に当たる処理は<code>_</code>とマッチさせます。</p> <h2><code>_</code>が使われている場合は無視される</h2> <p>C#は<code>string</code>も<code>switch</code>に使用できます。その場合、<code>case</code>には変数(定数)も使用できます。</p> <p>では<code>_</code>が既に変数(定数)として使用されている場合はどうなるでしょうか。</p> <pre><code class="csharp">var lastName = "八千崎"; const string _ = "雪村"; const string KuraueHinata_last = "倉上"; const string AobaKokona_last = "青羽"; const string SaitoKaede_last = "斎藤"; const string KurosakiHonoka_last = "黒崎"; var firstName = lastName switch { KuraueHinata_last => "ひなた", AobaKokona_last => "ここな", SaitoKaede_last => "かえで", KurosakiHonoka_last => "ほのか", _ => "あおい", }; Console.Write(firstName); // 出力結果:あおい </code></pre> <p>なんと、定数としての<code>_</code>とはマッチせずに、<code>default</code>のキーワードとしての<code>_</code>としてマッチしてしまいました。この結果、八千崎という人があおいちゃんと認識されてしまいました。これはまずい!</p> <p>まぁまずないとは思いますが、<code>_</code>という変数(定数)はうまくマッチングできないので使用を控えましょう。個人的には<code>out</code>引数でも特別な意味のあるキーワードなので<code>_</code>という変数などは宣言できないようにしてほしいのですが、まぁ後方互換性とかもあるのでね、仕方ないですね…。</p> <p>あおいちゃんとマッチングさせたくない場合は、面倒くさがらず</p> <pre><code class="csharp">var lastName = "八千崎"; const string AoiYukimura_last = "雪村"; const string KuraueHinata_last = "倉上"; const string AobaKokona_last = "青羽"; const string SaitoKaede_last = "斎藤"; const string KurosakiHonoka_last = "黒崎"; var firstName = lastName switch { AoiYukimura_last => "あおい", KuraueHinata_last => "ひなた", AobaKokona_last => "ここな", SaitoKaede_last => "かえで", KurosakiHonoka_last => "ほのか", _ => "そんな子おらん", }; Console.Write(firstName); // 出力結果:そんな子おらん </code></pre> <p>としましょう。</p> <h1>複数<code>case</code>とのマッチは不可</h1> <p>ただし、複数の<code>case</code>とマッチさせることはできません。</p> <p>具体的には、平日か休日かを判定したい場合、従来は</p> <pre><code class="csharp">var dow_eng = DateTime.Today.DayOfWeek; var workdayOrHoliday = ""; switch ((DayOfWeek)dow_eng) { case DayOfWeek.Monday: case DayOfWeek.Tuesday: case DayOfWeek.Wednesday: case DayOfWeek.Thursday: case DayOfWeek.Friday: workdayOrHoliday = "平日"; break; case DayOfWeek.Saturday: case DayOfWeek.Sunday: workdayOrHoliday = "休日"; break; default: workdayOrHoliday = "エラー"; break; } Console.Write(workdayOrHoliday); </code></pre> <p>この様に、月~金は平日、土・日は休日とまとめて指定できたのですが、新しい<code>switch式</code>ではそれができません。</p> <pre><code class="csharp">var dow_eng = DateTime.Today.DayOfWeek; var workdayOrHoliday = (DayOfWeek)dow_eng switch { DayOfWeek.Sunday => "休日", DayOfWeek.Monday => "平日", DayOfWeek.Tuesday => "平日", DayOfWeek.Wednesday => "平日", DayOfWeek.Thursday => "平日", DayOfWeek.Friday => "平日", DayOfWeek.Saturday => "休日", _ => "エラー", }; Console.Write(workdayOrHoliday); </code></pre> <p>と書くしかないんですね。これは嫌ですね。個人的には以下のような感じで書ければなと思っています。このコードは動きません。</p> <pre><code class="csharp">var dow_eng = DateTime.Today.DayOfWeek; var workdayOrHoliday = (DayOfWeek)dow_eng switch { DayOfWeek.Monday | DayOfWeek.Tuesday | DayOfWeek.Wednesday | DayOfWeek.Thursday | DayOfWeek.Friday => "平日", DayOfWeek.Sunday | DayOfWeek.Saturday => "休日", _ => "エラー", }; Console.Write(workdayOrHoliday); </code></pre> <p>今後拡張されるかもしれないので、楽しみに待とうと思います。</p> <p>ということでC# 8.0における<code>switch式</code>の備忘録でした。</p> <h1 id="おまけ"><a href="#%E3%81%8A%E3%81%BE%E3%81%91">おまけ</a></h1> <p>まぁ例が悪かったのでアレなんですけど、単純に日本語の曜日を取得するだけなら</p> <pre><code class="csharp">var culture_jpn = CultureInfo.GetCultureInfo("ja-JP"); var dow_jpn = DateTime.Today.ToString("dddd", culture_jpn); Console.Write(dow_jpn); </code></pre> <p>上記でできます。実行環境が日本語カルチャの設定になっているなら、カルチャの指定すら不要です。</p> <pre><code class="csharp">// 実行環境が日本カルチャの場合 var dow_jpn = DateTime.Today.ToString("dddd"); Console.Write(dow_jpn); </code></pre> あぱしょに tag:crieit.net,2005:PublicArticle/16860 2021-04-18T21:20:18+09:00 2021-04-18T21:20:18+09:00 https://crieit.net/posts/hide-trends-and-topics-on-web-twitter WEB版Twitterのトレンドとかトピックを非表示にする <p>TwitterのWEB版では、右側に「<strong>いまどうしてる?</strong>」(トレンド)や「<strong>おすすめユーザー</strong>」「<strong>おすすめトピック</strong>」などが表示されています。</p> <p><a href="https://crieit.now.sh/upload_images/65effe08f1a79b8612a3b12b55d32f4d607c236e54886.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/65effe08f1a79b8612a3b12b55d32f4d607c236e54886.jpg?mw=700" alt="001" /></a></p> <p>トレンドはともかく、トピックに関しては全然使っていないのでハッキリいって邪魔なんですよね。そもそも機能として不要と思うのですが、それに加えてフォローしていないトピックも突然TLに出てきて本当に邪魔です。不必要な情報が視界に入るとイライラするので消してしまいます。</p> <p>今回はGoogle Chromeで拡張機能を使用しますが、Microsoft EdgeやFirefoxなどもChromeの拡張機能を使用できるので、同じ方法で対応できます。</p> <p>使用する拡張機能は「Stylebot」という拡張機能です。</p> <p>手順は次の通りです。</p> <ol> <li>拡張機能「Stylebot」をインストール</li> <li>非表示にしたい部分を選択して非表示設定</li> </ol> <p>簡単ですね。</p> <p>まずは、<a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha?hl=ja">こちら</a>からアクセスし、「Chromeに追加」をクリックして有効化してください。</p> <p><a href="https://crieit.now.sh/upload_images/cd98267a2f4eaad828b5094c23951f48607c23831136c.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/cd98267a2f4eaad828b5094c23951f48607c23831136c.jpg?mw=700" alt="002" /></a></p> <p>次に、Twitterを開いて、拡張機能より「Stylebot」を開きます。</p> <p><a href="https://crieit.now.sh/upload_images/363a77cfcbdd967c9a726185ca7380c6607c2398049a2.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/363a77cfcbdd967c9a726185ca7380c6607c2398049a2.jpg?mw=700" alt="003" /></a></p> <p><a href="https://crieit.now.sh/upload_images/176a09eea04e0c7b6a7f69a5f8eb16f5607c23a6b42d0.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/176a09eea04e0c7b6a7f69a5f8eb16f5607c23a6b42d0.jpg?mw=700" alt="004" /></a></p> <p>すると、次のような画面が開きます。</p> <p><a href="https://crieit.now.sh/upload_images/b88cad9daa78e0e5db8aaca4192ee206607c23c0ed61a.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b88cad9daa78e0e5db8aaca4192ee206607c23c0ed61a.jpg?mw=700" alt="005" /></a></p> <p>非表示にしたい項目を選択して、「レイアウト」の「隠す」を選択します。</p> <p><a href="https://crieit.now.sh/upload_images/196fd4c4281c826ce76ebfd172f11217607c23ce5bd48.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/196fd4c4281c826ce76ebfd172f11217607c23ce5bd48.jpg?mw=700" alt="006" /></a><br /> <a href="https://crieit.now.sh/upload_images/e5901628e902ce86a1c4dde554e40e23607c23d812d45.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/e5901628e902ce86a1c4dde554e40e23607c23d812d45.jpg?mw=700" alt="007" /></a></p> <p>選択した「<strong>いまどうしてる?</strong>」が非表示になりました。</p> <p><a href="https://crieit.now.sh/upload_images/f4c4eee5776e9e0de0e5957a8bcad0ce607c23e427211.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/f4c4eee5776e9e0de0e5957a8bcad0ce607c23e427211.jpg?mw=700" alt="008" /></a></p> <p>同様に他の項目を選択すると、スッキリしました。</p> <p><a href="https://crieit.now.sh/upload_images/a30e5e8f27015c7c3c311d898a99c7fb607c23f209ae8.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/a30e5e8f27015c7c3c311d898a99c7fb607c23f209ae8.jpg?mw=700" alt="009" /></a></p> <p>この「Stylebot」は他にも文字の色などもカスタマイズすることができます。自分好みのTwitter環境にして、素敵なツイ廃ライフをどうぞ!</p> <p>ちなみに、手っ取り早く「<strong>いまどうしてる?</strong>」「<strong>おすすめユーザー</strong>」「<strong>おすすめトピック</strong>」を非表示にする場合、「Stylebot」の下の<code><> コード</code>のところに以下をコピペしてください。</p> <p>なお、Twitterの仕様などにより無効になったりレイアウトが崩れたりする可能性があります。</p> <pre><code class="css">.css-1dbjc4n.r-1ysxnx4.r-k0dy70.r-1867qdf.r-1phboty.r-rs99b7.r-1ifxtd0.r-1udh08x { display: none; } </code></pre> あぱしょに tag:crieit.net,2005:PublicArticle/16848 2021-04-15T20:19:11+09:00 2021-04-15T20:19:11+09:00 https://crieit.net/posts/what-i-want-to-tell-to-new-graduate-it-employees 新卒IT社員に伝えたいこと <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://togetter.com/li/1698737">プログラムを書いてエラーが出ると「自分が否定された」「尊厳を奪われた」と感じる人もいる、という話</a></p> <p>上記のまとめを読んで、何年か前にこういう新人さんがいたことを思い出しました。</p> <p>せっかくなので私も、IT新人さんへ向けてのTIPS的なものを書いてみようと思います。各所で言われていることかもしれないですが書いてみます。</p> <p>なお、あくまで私の個人的な考えなのであらゆる組織で通用する考えという訳ではないので注意してください。私自身はそんなに有名なサービスに関わっている訳でもない、ただの地方のエンジニアです。そんなに変なことは書いてないと思いますが、以下を鵜呑みにせず色々な人の「IT新人へのアドバイス」みたいな言葉を見て、必要な情報を取捨選択してください。また、分からない用語などが出てきたら都度ググってみてください。</p> <h1 id="エラーは怖くない"><a href="#%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AF%E6%80%96%E3%81%8F%E3%81%AA%E3%81%84">エラーは怖くない</a></h1> <p>上記のまとめでも言われていることですが、エラーを怖がる必要はありません。正確に言えば、本番で出たエラーは怖いんですが、開発中やテスト中はむしろどんどんエラーを出すべきだと個人的には思います。</p> <p>開発中やテスト中にエラーが発生すると、当然デバッグすることになります。すると本番ではそのエラーは発生しません。エラーは本番で発生すると、その調査や修正によりコストがかかります。</p> <p>それらは実際にリリースされて既に価値を生み出している製品なので、稼働を止めることによる機会損失や、ユーザーの信用を失うことに繋がるからです。</p> <p>一方、開発やテスト中にバグを見つけて修正することができれば、機会損失や信用の失墜を避けることができます。</p> <p>上記まとめにもありましたが、エラーや警告のメッセージはあなたを攻撃したりあなたを否定したりするものではありません。逆です。「こういうミスがあるよ」「ここの書き方がちょっとおかしいよ」「一応動くけどデータによってはエラーになるかもよ」と教えてくれるものです。</p> <p>動いているものが急に止まって、よくわからない英語がダラダラーっと出てくるので怖いかもしれませんが、一つ一つの文章はとても簡単な内容なので噛み砕いて理解するのは簡単だと思います。</p> <h1 id="使える機能やライブラリは積極的に使う"><a href="#%E4%BD%BF%E3%81%88%E3%82%8B%E6%A9%9F%E8%83%BD%E3%82%84%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AF%E7%A9%8D%E6%A5%B5%E7%9A%84%E3%81%AB%E4%BD%BF%E3%81%86">使える機能やライブラリは積極的に使う</a></h1> <p>あなたが何かの機能を作ることになった時、その「何か」は既に他の人が似たようなものを作ったりしていることがあります。</p> <p>それを自分でやることは、それはそれで良い経験になったりはしますが、ITエンジニアは「面倒なことや難しいことを1と0で解決させる」ことです。要は、基本的に面倒くさがりな人が向いている気がします。誰かが既に作っているものを自分で新しく作るのこと(<a target="_blank" rel="nofollow noopener" href="https://ja.wikipedia.org/wiki/%E8%BB%8A%E8%BC%AA%E3%81%AE%E5%86%8D%E7%99%BA%E6%98%8E">車輪の再発明</a>と言ったりします)は基本的にはやめた方が良いでしょう。</p> <p>特にOSSなどで広く公開されているライブラリなどは積極的に導入を検討するのも良いでしょう。それらはあなたが個人で開発するよりも、より大勢の人の目によって使われて何度もバグが修正されていたり、最適化されていたりします。</p> <p>ただ一点勘違いしてほしくないのは、「自分で書かないだけで、書こうと思えば書ける」という状態にはなっておいた方が良い、ということです。</p> <p>たとえば配列のソートなんかは、だいたいどの言語でも<code>array.sort</code>的なメソッドがあります。ソートをするならそれを使えば良く、わざわざソート用のメソッドをあなたが0から実装する必要はありません。</p> <p>ただし、「じゃあソートってどういうアルゴリズムなの?<code>sort</code>っていうメソッドの中では何をやってるの?」という状態は好ましくないと個人的には思います。そういう状態であれば、ソートをするメソッドを書いてみるのも良いでしょう。それにより配列の特性を学んだり、なぜこの処理だと時間がかかるのか、なぜこの書き方が推奨されるのか、などを実体験として獲得できます。これは大きなアドバンテージで、この体験を積み上げていくことがとても大切です。後に同じような問題が発生した時も、これらの経験から「ここが怪しいんじゃない?」となんとなく分かるようになります。</p> <p>また、エディターによっては変数名やメソッド名の自動補完や、より良い方法を示したりする機能もありあます(EclipseのContent AssistやVisualStudioのIntelliSenseなど)。それらは便利な反面、「関数名などを中途半端にしか覚えなくなったりタイピングが上達しなくなったりするなどの理由から、新人さんには使わないように言っている」という人に一度だけ会ったことがありますが、個人的には使えるものはなんでも使って言った方が良いと思います。</p> <p>どうせ関数名は英語が分かればだいたい分かるし、何度も使ううちに覚えていきます。タイピングの上達は確かに大事なことですが、入力補完でtypoを減らせるのも充分なメリットです。毎日何時間もキーボードを叩いていれば自然にタイピングは上達すると思います。それにどうせ後から使う機能ならば最初から慣れておいた方が良いと思います。私だったら、気になったものはなんでも使ってみるように指導します。</p> <h1 id="ネットから拾ってそのまま使わない"><a href="#%E3%83%8D%E3%83%83%E3%83%88%E3%81%8B%E3%82%89%E6%8B%BE%E3%81%A3%E3%81%A6%E3%81%9D%E3%81%AE%E3%81%BE%E3%81%BE%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84">ネットから拾ってそのまま使わない</a></h1> <p>上記と少し矛盾するかもですが、ネットからコードを適当に拾ってきてそのまま使うのは避けた方が良いでしょう。</p> <p>理由は以下の2つです。</p> <ol> <li>そのまま使うだけでは得るものがないから</li> <li>ライセンス的に問題があることがあるから</li> </ol> <p>まず1点目ですが、たとえば何かしらの関数をググってコピペして、それであなたがやりたかったことが実現できたとします。すると、あなたのコードを見た先輩や上司が「ここはなんでこの変数名なの?」「なんでこういう書き方をしているの?」などと疑問に思うかもしれません。</p> <p>そのような質問をされた時に、ネットから拾ってコピペしただけだとスムーズに答えることができません。これだと、先輩の疑問も解消されませんし、何一つ学べていないということになります。ググってコピペするというだけの簡単な作業ですが、せっかくなら何をしているか分かった方が良いですよね?</p> <p>特にITの世界は移り変わりが激しいので、その記事が書かれた当時ではモダンなコードだったとしても、1~2年経ったら古臭い書き方、懐かしい書き方になっていることもザラにあります。古臭い書き方が常に悪という訳ではないのですが、コードを見る人は「なんでわざわざこんな書き方してるんだろう?」と疑問に思う訳ですね。</p> <p>また、致命的なバグが含まれている可能性もあります。私が執筆している記事に関してもその可能性はあります。そして、仮にコピペしたコードがバグを引き起こして何かしらの損害を被っても、そのコードを書いてネットに載せた人は一切責任を取ってはくれません。</p> <p>2点目は、ライセンスの問題です。無償公開してあるものでも、MITライセンスなどは著作権表示が必要です。ライセンスポリシーによっては料金が発生するものもあるでしょう。当然不正使用となると重大な問題、コンプライアンス違反となります。</p> <h1 id="アウトプットするクセをつける"><a href="#%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E3%81%99%E3%82%8B%E3%82%AF%E3%82%BB%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B">アウトプットするクセをつける</a></h1> <p>得た情報は積極的にアウトプットした方が良いです。なぜなら、アウトプットして他の人の視点が入れば、「ここはこんな感じにも書けますよ」とか「他にもこんなに便利なツールがありますよ」など意見交換に繋がるからです。発信した内容(自分が事実だと思っていたこと)に誤りがあればそれを指摘してもらい、正しいことを知るきっかけになったりします。</p> <p>そしてアウトプットしておくことで、後から自分が見直すことができます。「久々に〇〇をやろうとしてググったら自分が書いたページがヒットした」みたいなのも、たまに見聞きします。</p> <p>アウトプットするのもいくつか方法はありますが、オススメなのは<a target="_blank" rel="nofollow noopener" href="https://qiita.com/">Qiita</a>です。アカウントを作っていなければ今すぐにでも作って良いと思います。他にも私が利用している<a href="https://crieit.net/">Crieit</a>や<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>、ブログを書くというのもあります。QiitaもCrieitも、ブログではWordpressやはてなブログでもそうですが、Markdownで記事を書くことができます。Markdownに慣れておくのも良いと思うので、練習がてら書いてみると良いでしょう。</p> <p>また、「今から調べることは後からまとめてアウトプットするんや…!」というつもりで情報を集めると、不思議なことに集められる情報の質が上がります。自分の理解を越えて良いアウトプットをすることは出来ないので、良いアウトプットをするなら必然的に自分の理解度を上げることに繋がります。これは最終的に自分が得をします。</p> <p>また、アウトプットのクセを付ければ、他の人がわかりやすい表現をする練習にもなります。自分だけが分かる書き方ではなく、誰にとっても分かりやすい表現ができるようになります。信じられないかもしれませんが、人によっては「ボタンを押したらデータと日付を画面にオープンする」みたいなことを仕様書に書く人もいます<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。結局「どのデータか」「日付はどういうフォーマットか」「画面にオープンするとはどういう意味か」などといちいち質問する必要があり、それは双方にとって不必要なコミュニケーションコストです。初めから分かりやすく書かれているに越したことはありません。</p> <h1 id="道具にこだわる"><a href="#%E9%81%93%E5%85%B7%E3%81%AB%E3%81%93%E3%81%A0%E3%82%8F%E3%82%8B">道具にこだわる</a></h1> <p>あらゆる道具にこだわりましょう。キーボード、マウス、モニター、机、椅子、OS、エディター、その他ツール…挙げればキリがありません。</p> <p>キーボードなら日本語配列か英語は配列か、フルサイズかテンキーレスか、キーピッチはどうするか、直行配列にするか、セパレートキーボードにするか、トラックポイントは必要か、ワイヤレスか有線か、キースイッチは何方式か、メカニカルなら何軸か。モニターは何枚にするか、アームはつけるか、縦置きか横置きか、インチ数はどうするか、画面解像度はどうするか、デイジーチェーンにするか、など色々と拘こだわることができます。</p> <p>会社の都合などで、特にハードウェアは望み通りのものを使えないことがあるかもしれませんが、こだわることは大事だと思います。たとえばタイピングしやすいキーボードはそれ自体がモチベーションにもなりますし、見た目でも性能でも気に入れば愛着がわいて長く使いたくなります。職業柄PCに向き合う時間も長くなるので、せっかくなら徹底的にこだわって好きなもので固めた方が楽しいです。</p> <h1 id="便利なショートカットを覚える"><a href="#%E4%BE%BF%E5%88%A9%E3%81%AA%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E3%82%92%E8%A6%9A%E3%81%88%E3%82%8B">便利なショートカットを覚える</a></h1> <p>ショートカットはめちゃくちゃ便利です。使いこなせばキーボードからマウスに持ち替える動作が大幅に減り効率化できます。</p> <p>Windowsであれば</p> <ul> <li><code>Ctrl</code> + <code>C</code>(コピー)</li> <li><code>Ctrl</code> + <code>X</code>(切り取り)</li> <li><code>Ctrl</code> + <code>V</code>(貼り付け)</li> <li><code>Windows</code> + <code>E</code>(エクスプローラーを開く)</li> <li><code>Alt</code> + <code>D</code>(エクスプローラーやブラウザのアドレスバーにフォーカス移動する)</li> <li><code>Alt</code> + <code>Tab</code>(表示中のウィンドウを切り替える)</li> <li><code>Windows</code> + 数字(タスクバーにピン留めしているアプリを起動)</li> </ul> <p>あたりはマジでよく使うと思います。普段から慣れておくと良いでしょう。付箋などに書いて目に入る場所に貼っておくのも良いと思います。</p> <h1 id="タイピングに早く慣れる"><a href="#%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0%E3%81%AB%E6%97%A9%E3%81%8F%E6%85%A3%E3%82%8C%E3%82%8B">タイピングに早く慣れる</a></h1> <p>馬鹿にしている訳ではないですが、「最近の新人さんはスマホ世代なので、タイピングに慣れていないどころかローマ字もよく分からない人が結構いる」みたいな発言を見ました。その状態ではプログラミングはおろか、チャットやメールなども難しいと思うので、とりあえずさっさとタイピングに慣れましょう。</p> <p>上記にある通りアウトプット記事を書いてみたり、<a target="_blank" rel="nofollow noopener" href="http://typingx0.net/sushida/">寿司打</a>などのタイピングゲームをすれば慣れてくると思います。ホームポジションを覚えればかなりタイピングもスムーズになるでしょう。たまにタイピングが遅くてホームポジションもめちゃくちゃだけどめっちゃ優秀な人もいますが、まぁしっかりタイピングできるに越したことはないと思うのでしっかり慣れましょう。</p> <p>プログラミングはほとんどが英語の単語や文章なので、ローマ字のタイピングは得意でも英単語はスムーズにタイピングできないという人もいます。できれば練習の段階で英単語も挑戦するようにしましょう。</p> <p>タイピングに関してはキーボードとの相性も関わってきますので、自分にあったキーボードを見つけることも重要です。特にホームポジションは変な癖がつくとなかなか矯正できません。私も昔はずっと小さいキーボードを使っていて変な癖がついてしまっています。</p> <h1 id="わからないことをわからないまま放置しない"><a href="#%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%93%E3%81%A8%E3%82%92%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%BE%E3%81%BE%E6%94%BE%E7%BD%AE%E3%81%97%E3%81%AA%E3%81%84">わからないことをわからないまま放置しない</a></h1> <p>これが結構大事かもしれません。わからないことをわからないまま放置すると、後から調べるにも面倒になります。ググれば10秒もかからず調べることができるのですから、せめて概要だけでも知るようにしましょう。SiriやGoogleアシスタント、Alexaなどの音声アシスタントサービスを利用するのも良いでしょう。</p> <p>ミーティングにPCやタブレットなどを持ち込めるのであれば、ミーティング中に出てきたよく分からん単語をその場で調べたり、メモしておいて後でググったりすると良いでしょう。ミーティングがオンラインであればなおさら簡単にできますね。ちなみに弊社は絶賛オフラインです、本当にありがとうございました。</p> <p>一般的なことであればググれば分かることが多いですが、詳しい人に聞くのも効果的です。その人独自の視点や体験を交えて教えてくれるかもしれないですし、ググるだけではたどりつけない情報を知ることができるのも、人に質問することの大きなメリットです。人間は知識をひけらかしたい生き物なので、質問されて嫌な人はそんなにいないと思います。先輩だろうが上司だろうがガンガン質問していきましょう。</p> <h1 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h1> <p>色々と書きたいことはありましたが、まぁ概ねかけたと思います。他にも「ググる力を付ける」「情報取捨選択の力を付ける」「手段にこだわりすぎない」なども書こうと思ったのですが上手くまとめられなさそうなのでやめました。要望があったら書きますので、Twitterなどで反応いただければと思います。</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>Qiitaに記事はほとんど書いていませんが、アカウントは作っています。Crieitを利用している理由は、メインでブログを書いており、カノニカルURLを設定がQiitaではできずCrieitではできるからです。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:2" role="doc-endnote"> <p>組織やチーム内で、最終的なイメージや暗黙の仕様が充分に共有されていればこの粒度でも良いこともありますが…。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> あぱしょに tag:crieit.net,2005:PublicArticle/16756 2021-03-17T21:06:15+09:00 2021-03-17T21:06:15+09:00 https://crieit.net/posts/easy-hack-to-put-a-signature-for-pixiv 【Windows】pixivの署名を簡単に入れよう <p>以前公開した<a href="https://crieit.net/posts/easy-hack-to-copy-date-yyyymmdd">「【Windows】日付8桁(yyyymmdd)を簡単にクリップボードに入れる方法」</a>という記事が意外と読まれていたので、その応用版みたいな話です。</p> <p>今回はpixivに投稿するイラストなどに入れるサインではなく、説明欄に入れるフッター的な意味の署名の話です。</p> <p>私も少し前からpixivやFantiaには署名を入れています。</p> <p><a href="https://crieit.now.sh/upload_images/57337ff99737f295753fdda886cce76d6051f0916f467.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/57337ff99737f295753fdda886cce76d6051f0916f467.jpg?mw=700" alt="001" /></a></p> <p>こんな感じですね。</p> <p>これをやると作品を見てくださった方が他のTwitterやブログなど、他の活動場所にも来ていただきやすくなるかな~…と思って入れています。期間が短く、別に計測している訳ではないので効果の程はわかりませんが。</p> <p>この署名、入れるのはいいのですが毎回以前のページからコピペするのって結構面倒くさいので、スクリプトで「署名をクリップボードに入れる」ところまでは自動化しています<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。</p> <p>今回は、署名を書いたテキストファイルを別途用意して、そのファイルの内容をクリップボードに入れるためのスクリプトを用意します。</p> <p>まず署名ファイルを作成します。</p> <p>内容は好きに書いてください。署名のほかに簡単なメッセージなどを入れるものありでしょう。</p> <blockquote> <p>ほげほげ丸<br /> Blog https://example.com<br /> 無断転載はお控えください。<br /> Please do not reprint without my permission.</p> </blockquote> <p>これを<code>txt</code>で保存しますが、文字コードに<code>ANSI</code>を選んでください。他の文字コードだと文字化けしてしまいます。ファイル名はなんでもいいです。ここでは、「signature.txt」という名前で保存したとします。</p> <p>次に、バッチファイルを作成します。作成の仕方は冒頭で紹介した記事を参照してください。</p> <pre><code class="bat">clip < "signature.txt" </code></pre> <p><code>signature.txt</code>の部分は、先ほど作成したファイルに置き換えてください。これもファイル名はなんでもいいですが、「.bat」以外の部分を自分でタイプするので短くて覚えやすい名前の方が良いと思います。また、これも文字コードは<code>ANSI</code>を選んでください。「signature」を略して「sig」とかにすると覚えやすいと思います。「shomei」とかでも良いかも。まぁなんでもいいです。</p> <p>ファイル名にスペースを使っていない場合は、テキストファイル名を<code>"</code>で囲む必要はありません。スペースを入れる場合(「signature pixiv.txt」にする場合など)は、<code>"</code>で囲んでください。空白が入る場合は、<code>"</code>で区切らないと別のコマンドと認識され、正常に動作しません。</p> <p>あとは作成したテキストファイル(.txt)とバッチファイル(.bat)にPATHを通せば完了です。PATHを通す方法も、冒頭で紹介した記事を参照してください。</p> <p>これを実行して、テキストファイルに作成した署名がクリップボードに入っていることを確認してください。</p> <p>私は署名をpixiv用とFantia用に使い分けているので<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>、テキストファイルとバッチファイルをそれぞれ2つずつ作成し「sip」「sif」というコマンドで運用しています。(それぞれ「<strong>si</strong>gnature <strong>p</strong>ixiv」と「<strong>si</strong>gnature <strong>f</strong>antia」略です)</p> <p>これで、いちいち過去の作品からコピーとかしなくて済みます。いつでも<code>Windows</code>キーを押して<code>sigp</code>と入力して簡単に署名をコピーできます。やったね!</p> <p>まぁこんなもの用意しなくてもpixiv側で、各作品に共通の署名を入れられるようにしてくれればそれが一番いいんですけどね。プレミアム限定機能でもいいので…。YouTubeとかは確か、デフォルトのアップロード設定とかで概要のテンプレートを作れた気がします。最悪ああいうのでもいい。</p> <p>これを応用して、「頻繁に入力したい文字列」があるならコマンド化すると楽かもしれません。メールの署名とかは、各メーリングソフトの機能を使った方が楽だと思います。</p> <p>よかったらついでに私の<a target="_blank" rel="nofollow noopener" href="https://www.pixiv.net/users/4965862">pixiv</a>と<a target="_blank" rel="nofollow noopener" href="https://fantia.jp/fanclubs/26396">Fantia</a>を見てください(小声)</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>DOM操作で署名を挿入するようなJavaScriptのコードをブックマークしておき、pixivのページ上で呼び出すという感じで簡単にできると思いますが、やっていいかどうか分からないのでここでは書きませんし推奨もしません。試したい人は自分で調べて自己責任でやってください。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:2" role="doc-endnote"> <p>FantiaはURLの内容を勝手に展開してカード状にしてくれるおせっかいな機能があり、それによりデザインが損なわれるので「https://」を省略した文字列を署名に出すようにしています。リンクにはなりませんが見た目崩れるよりは良いので…。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> あぱしょに tag:crieit.net,2005:PublicArticle/16719 2021-03-05T21:11:41+09:00 2021-03-06T03:57:48+09:00 https://crieit.net/posts/easy-hack-to-copy-date-yyyymmdd 【Windows】日付8桁(yyyymmdd)を簡単にクリップボードに入れる方法 <p>PCで作業をしていると、フォルダ名とかファイル名に日付8桁を入れたたいなと思うことがあると思います。例えば2021年3月5日なら「20210305」とかですね。</p> <p>日付を確認して入れるだけなのですが、いちいちカレンダーを確認するのもめんどいし入力するのもめんどいので楽にできる方法を考えました。</p> <p>あまり詳しくない方に向けて書いていますので詳しい方からすると長ったらしいと感じられるかもしれませんが、分かる箇所は適宜読み飛ばしてください。</p> <h2 id="手順"><a href="#%E6%89%8B%E9%A0%86">手順</a></h2> <ol> <li>クリップボードに日付8桁(yyyymmdd)を入れてくれるバッチファイルを用意する</li> <li>PATHを通す</li> <li>バッチを実行する</li> </ol> <p>の3点です。</p> <h2 id="バッチファイルを用意"><a href="#%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%94%A8%E6%84%8F">バッチファイルを用意</a></h2> <p>メモ帳を開いて、以下の内容をコピペしてください。</p> <pre><code class="bat">SET /P ="%date:~0,4%%date:~5,2%%date:~8,2%"< nul | clip </code></pre> <p>ファイルを保存します。この時、ファイルの種類は「すべてのファイル(<em>.</em>)」を選択してください。また、ファイル名は「.bat」まで入力してください</p> <p><a href="https://crieit.now.sh/upload_images/c576981c6bc43e5eacaf40e4b74a7d1d60421f9c1b7d2.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/c576981c6bc43e5eacaf40e4b74a7d1d60421f9c1b7d2.jpg?mw=700" alt="001" /></a></p> <p>ファイル名は任意の名前をつけてください。ただし、日付をクリップボードにコピーする際にこのファイル名の「.bat」を除いた部分を入力するので、短くて覚えやすいファイル名が良いです。</p> <p>私は日付(date)8桁ということで「d8.bat」としています。</p> <p>また、保存先のフォルダはどこでも問題ないので、任意のフォルダに保存してください。デスクトップでもOKです。</p> <p>ファイルを保存したら、ダブルクリックして実行してください。上手く出来ていれば、一瞬黒い画面が表示されると思います。</p> <p>また、適当なメモ帳などに貼り付けをして、日付8桁がコピーされていることを確認してください。</p> <p>簡単に内容を解説しますと、<code>%date%</code>というのは日付を「/」区切りで表示するのですが、今回は「/」部分はいらないので数字の部分だけを抜き出して、クリップボードに格納しています。</p> <h2 id="PATHを通す"><a href="#PATH%E3%82%92%E9%80%9A%E3%81%99">PATHを通す</a></h2> <p>通常、ファイルを実行するにはそのファイルが保存されているフォルダの位置を教えて実行する必要があります。単に「d8.bat」を実行するように命令しても、PCは「d8.batがどこにあるか分からない」ので実行できません。</p> <p>しかし、PCに「d8.batというファイルはこのフォルダにあるよ」と予め教えてあげることで、「d8.batを実行してね」という命令だけで実行してくれるようになります。</p> <p>「ファイルがここにあるよ」とPCに教える作業を「PATHを通す」と言ったりします。その作業をここでは行います。</p> <p>PATHを通すにはPCの設定を行う必要があります。</p> <p><code>Windows</code>キーを押して「path」と入力すると、「環境変数を編集」というメニューが現れるのでクリックします。<br /> <a href="https://crieit.now.sh/upload_images/8f3b8bdb9e0883525065ea3e0cd1307860421fab3e5df.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/8f3b8bdb9e0883525065ea3e0cd1307860421fab3e5df.jpg?mw=700" alt="002" /></a></p> <p>「Path」というところをクリックし、「編集(E)...」をクリックします。<br /> <a href="https://crieit.now.sh/upload_images/cbea3bab4c65185bc9d9fb45d6a1b9d560421fbaaf0b8.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/cbea3bab4c65185bc9d9fb45d6a1b9d560421fbaaf0b8.jpg?mw=700" alt="003" /></a></p> <p>「新規(N)」をクリックします。<br /> <a href="https://crieit.now.sh/upload_images/4a5454b9256fcff5db6b0ce92923e64960421fcaa25ba.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/4a5454b9256fcff5db6b0ce92923e64960421fcaa25ba.jpg?mw=700" alt="004" /></a></p> <p>すると、入力用のテキストボックスが表示されるので、ファイルを保存したフォルダをここに入力します。<br /> <a href="https://crieit.now.sh/upload_images/0e267e044307aa6373acaa767e0cf79160421fd90594f.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/0e267e044307aa6373acaa767e0cf79160421fd90594f.jpg?mw=700" alt="005" /></a></p> <p>たとえば、「D:\tools」というフォルダに保存した場合は、「D:\tools」と入力します。</p> <p>エクスプローラーのアドレスバーからコピーすることもできます。<br /> <a href="https://crieit.now.sh/upload_images/8bf9109c698ed9bad11575df1ee3e6ca60421fe67a062.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/8bf9109c698ed9bad11575df1ee3e6ca60421fe67a062.jpg?mw=700" alt="006" /></a></p> <p>入力したら、「OK」をクリックします。<br /> <a href="https://crieit.now.sh/upload_images/4b14d515a7c15e9a6bcba8bfd309eae460421ff1efbf6.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/4b14d515a7c15e9a6bcba8bfd309eae460421ff1efbf6.jpg?mw=700" alt="007" /></a></p> <p>これでPATHを通すことができました。あとは、コマンドプロンプトなどから保存したファイルの名前を実行すれば、クリップボードに日付8桁が保存されます。</p> <h2 id="実行"><a href="#%E5%AE%9F%E8%A1%8C">実行</a></h2> <p>コマンドプロンプトやPowerShellから実行するほか、エクスプローラーのアドレスバーなどからでも「d8」で実行できます。特にエクスプローラー上でサクッと実行できるのは、いちいちコマンドプロンプトやPowerShellを立ち上げなくてよいので便利ですね。</p> <p>また、日付のフォーマットも自由に調整できます。たとえば日時まで入れたい場合は、最初のバッチファイルの内容を変更すれば可能なので、好きにアレンジして使ってみてください!</p> <p>定期的に貼り付けたい定型文字列なんかも、別のファイル名で登録すると色々はかどるかもしれません。簡単なスクリプトで便利にできるハックは意外と多そうですね!</p> あぱしょに tag:crieit.net,2005:PublicArticle/16711 2021-03-02T20:29:59+09:00 2021-03-02T20:29:59+09:00 https://crieit.net/posts/csharp-strangeness-in-a-simple-using-statement 【C#】「単純なusingステートメント」の違和感 <p><code>using</code>は外部リソースを確実に解放するために用いる。</p> <p>たとえば、</p> <pre><code class="csharp">using (var sw = new StringWriter(filePath, append: true, Encoding.UTF8)) { sw.Write(hoge); } </code></pre> <p>と書けば、スコープを抜けた時点でファイルが確実に解放される。いちいち<code>Close</code>とか<code>Dispose</code>とかしなくて済むのだ。これは素晴らしい。</p> <p>処理が単一ステートメントであれば<code>{}</code>は省略できるので、</p> <pre><code class="csharp">using (var sw = new StringWriter(filePath, append: true, Encoding.UTF8)) sw.Write(hoge); </code></pre> <p>このように書ける。これも全く同じ意味で、<code>if</code>の<code>{}</code>を省略しているのと変わらない。ので、今までこう書いていたが、C#8.0では以下のようにメッセージが表示される。</p> <blockquote> <p>IDE0063:'using'ステートメントは単純にできます</p> </blockquote> <p>推奨の修正を適用すると、</p> <pre><code class="csharp">using (var sw = new StringWriter(filePath, append: true, Encoding.UTF8)); sw.Write(hoge); </code></pre> <p>となる。これも動くんだけど違和感がすごい。なんというか、<code>using</code>の後に<code>{}</code>があればスコープはそこに限定されるし、なければ次の単一処理がスコープになっているとはっきりわかる。</p> <p>でもこれ、</p> <pre><code class="csharp">using (var sw = new StringWriter(filePath, append: true, Encoding.UTF8)); sw.Write(hoge); sw.Write(fuga); </code></pre> <p>ってかけるんだよね。で、<code>fuga</code>も書き込まれるんだよね。じゃあスコープはいつまで有効なの?というと、その変数の範囲らしい。</p> <p>個人的には使わなくなったらとっとと<code>Dispose</code>しないと気持ち悪いので、IDEの警告を抑制して無視して、従来通り<code>{}</code>を必要に応じて使ってスコープを明記することにした。もっとも、そこだけメソッドに切り出して単純な<code>using</code>を使うのが一番スマートなのかもしれないが。</p> あぱしょに tag:crieit.net,2005:PublicArticle/16599 2021-01-14T20:07:57+09:00 2021-01-14T20:07:57+09:00 https://crieit.net/posts/nothing-on-desktop デスクトップには何も置かない <p>仕事でもプライベートでも、PCのデスクトップにはファイルやフォルダを置かない派です。ショートカットも置きませんし、ゴミ箱も非表示。一切のモノを置きません。何年か前からそうしています。</p> <p>なんかデスクトップに色々なファイルが乱雑に置かれていると気が散るんですよね。PC起動した時に色々視界に入るのが嫌というか…。</p> <p>特にプライベートで使っているPCはお気に入りの壁紙とかを設定していたりするので、それが隠れるのが嫌です。せっかくお気に入りの壁紙にしているのだから隠したくないです。</p> <p>なんというか、私は自分のことをミニマリストではないと思っているのですが、PCのデスクトップ画面には何も置きたくないし、タスクバーに関しては最低限のものしか置きたくない派<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。というかタスクバーも常時非表示にできるなら常時非表示にしたいと思っています。Windowsでは「自動で隠す」はできるんですけど常時非表示はできない…。「自動で隠す」だとタスクバーがある付近にマウスカーソルを当てるとピョコって出てくるのですが、それが嫌だ。余計に気が散ります。それなら表示されてていいよ、って思うので小さいタスクバーを使っています。</p> <p>慣れてしまえばデスクトップにファイルとかショートカットとかなくても別に何も困らないんですよね。ソフトの起動もキーボードでできますし。キーボードから手を放してマウスでアイコンをポチってするよりキーボード叩く方が早いですし。PC起動してからマウス一切しようせずサインインする訳ですから、作業始める時にいちいちマウス触りたくないというのもあります。</p> <p>というかプライベートではファイルはほとんどNASに置いておりローカルのファイルを編集するようなことがほとんどないので、置くファイルがそもそもないんですけどね。</p> <p>スクリーンショット(またはハードコピー、または画面キャプチャ、他)を一時的にデスクトップに保存することはありますが、それも用が済んだらすぐに削除していますね。(そもそも<code>Windows</code>+<code>Shift</code>+<code>S</code>を使うことが多いですが)</p> <p>ちなみに「デスクトップに乱雑にファイルを置いたら重くなるから私は置いていません(キリッ)」という人がたま~にいますが、正直そこまで影響ないだろ…と思っています。デスクトップはCドライブ上にあるので理論上起動時間に影響するかもしれませんが、あったとしても軽微なものでしょう。少なくとも最近のPCを使っていて、デスクトップ上のファイルの有無で起動時間を体感できるようなことはないんじゃないかなぁと思っています。</p> <p>私がそのように運用しているのは単に気が散るからそうしているだけです。</p> <p>そもそもデスクトップって「机の上」ですからね。使わん書類とか(ファイル)を机の上に置いているよりは、引き出し(ディレクトリ)に入れて整理した方がなんとなく気持ちいと思います。まぁ人によると思いますが。</p> <p>ちなみにググってみると<a target="_blank" rel="nofollow noopener" href="https://diamond.jp/articles/-/185453">仕事ができる人はデスクトップにファイルを置かない</a>というすごく強いタイトルの記事がヒットしましたが、このタイトルはちょっとどうかと個人的には思いますね。デスクトップに色々置いている人で仕事ができる人もたくさんいますし、逆にデスクトップがきっちり整理されていても仕事のできない人もたくさんいるでしょう。要は個人が使いやすいように最適化されているかどうかであって、あんまり因果関係はない気がしますね。</p> <p>仕事でも必要なファイルやショートカットなどは特定のディレクトリ(たとえばD:\workみたいな)に置いていますし、デスクトップにファイルがなくて困ることは何一つないですね。</p> <p>フォルダを開くにしても<code>Windows</code>+<code>E</code>でエクスプローラーの起動、<code>Alt</code>+<code>D</code>でアドレスバーにフォーカスできるので、あとは目的のパスを入力するだけです。慣れてしまえばマウスでクリックして潜っていくよりも絶対に速いですし。<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p> <p><code>Windows</code>でスタートメニュー開いて数文字タイプするだけでソフトも起動できます。例えば「vsc」ならVisualStudio Code、<br /> 「notepad」ならメモ帳、「calculator」なら電卓、「mspaint」ならペイントみたいに。実際はサジェストが効くので「not」「calc」「msp」あたりまで打ち込んだところで候補に出るので<code>Enter</code>を叩くだけです。絶対こっちの方が楽だし速い。マウスを持ち替えなくていいし。(<code>Windows</code>+<code>R</code>でやってもいいですが)</p> <p>ローカルにファイルが色々あるなら<a target="_blank" rel="nofollow noopener" href="https://chocolatey.org/packages/Everything">Everything</a>とかを使えばサクッと検索できて楽ですね。(私の場合はNASをマウントしているのであまり使いませんが…)</p> <p>デスクトップにファイルを置かないような運用のメリットをまとめると</p> <ul> <li>気が散らない</li> <li>壁紙がしっかり見れるので嬉しい</li> <li>いちいちマウスに持ち変える動作が減るので時短になる(かも)</li> <li>ショートカットとか覚えるようになる(かも)</li> </ul> <p>もしやってみようかな!って人がいたらやってみればいいと思います。なかなか快適ですよ。慣れなかったら元のスタイルに戻せばいいしね。</p> <p>ちなみにこの記事は弊社の某に「デスクトップにファイル置かないとパッと探せないでしょ、置いた方がいいよ~」と言われておこだったので「うるせいやいうるせいやい!」と半ベソで書きました。各々やりやすいようにやれば、別にどんな運用しようがどーでもいーじゃんと思うのですがいかがでしょうか。</p> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>多少ならいいですがMacのDockみたいなズラズラズラーってなってるのは苦手です。絶対気が散る。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:2" role="doc-endnote"> <p>ちなみにアドレスバーで<code>cmd</code>や<code>powershell</code>と打つとそのパスをカレントパスにしてコマンドプロンプトやPowerShellが立ち上がります。そういう時も<code>Alt</code>+<code>D</code>が便利ですな。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> あぱしょに tag:crieit.net,2005:PublicArticle/16589 2021-01-13T20:55:23+09:00 2021-01-14T18:55:08+09:00 https://crieit.net/posts/what-should-be-written-in-the-comment 【C#】コメントに書くこと、書かないこと <p>※C#としているがC#以外でも同じで、サンプルコードをC#で書いているのでタイトルにC#とつけた。</p> <p>プログラミングを行う上で、コメントの重要性は大きい。適切なコメントを書けばコードを読む人の助けになる。逆に、どうでもいいコメントや嘘のコメントを書けばそれは悪影響をもたらす。</p> <p>コメントに関しては宗教のようなものなので初めに私のポリシーを明記しておく。この記事の内容もこれに沿って展開する。</p> <ul> <li>コードを読んだら秒でわかることはコメントに書かない</li> <li>コードを読んだらわかるが読むのに時間がかかりそうな時は書く</li> <li>なぜこのようなロジックになっているかを書く</li> <li>拡張・修正する際に、罠になりそうな箇所の警告を書く</li> <li>コメントで説明するくらいなら命名を見直す</li> <li>変更前のソースをコメントアウトして残さない(論外)</li> </ul> <p>この記事の内容はあくまで私が考えていることの表明であって、「私の意見が絶対的に正しい」とか「コメントはこう書かれるべきである」という趣旨の内容ではない。念のため書いておく。</p> <h1 id="コードを読んだら秒でわかるようなことはコメントに書かない"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E8%AA%AD%E3%82%93%E3%81%A0%E3%82%89%E7%A7%92%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8B%E3%82%88%E3%81%86%E3%81%AA%E3%81%93%E3%81%A8%E3%81%AF%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AB%E6%9B%B8%E3%81%8B%E3%81%AA%E3%81%84">コードを読んだら秒でわかるようなことはコメントに書かない</a></h1> <p>正確に言うと、書く必要がない。なにせ読んだら秒でわかるのだから。</p> <p>極端な例だが、以下のようなコメントは不要だ。</p> <pre><code class="csharp">// 〇〇さん(xx) var nameAndAge = $"{name}さん({age})"; </code></pre> <p>これは、変数を「〇〇さん(xx)」の形に整形しているが、<strong>そんなもん見たらわかる</strong>のである。</p> <p>見たらわかることをいちいちコメントに書く必要はない。何故か?</p> <p>それは、ソースを修正する時にコメントも修正する必要が出てくるからだ。</p> <p>上記コードを以下のように修正したとしよう。</p> <pre><code class="csharp">// 〇〇さん(xx) var nameAndAge = $"{name}さん({age}歳)"; </code></pre> <p>コードは修正したが、コメントの修正を忘れたとする。するとどうなるか。</p> <p>ソースを見ると「〇〇さん(xx歳)」となっているが、コメントは「〇〇さん(xx)」となっている。これを見た人は、「どっちが正しい仕様なんだろう?」と頭を悩ませるのである。そして仕様を確認するという手間が発生するし、コメントを修正する(あるいは修正を指示する)という手間も発生することだろう。</p> <p>書いていなければ「ふーん、『〇〇さん(xx歳)』の形式ね。」とスムーズに読めるのに、コメントがコードの内容と違っているばかりに余計な手間がかかる。これは完全に悪である。</p> <p>「いやいや、普通はコードと一緒にコメントも修正するでしょ」と言う人もいるかもしれないが、そういう普通の人と一緒に働いてみたい。特にコード変更に対して充分な時間が与えられないことは往々にしてあり、急いで修正、テスト通るかのチェックをしてレビュアーに投げるというものだろうが、経験上ほとんどのレビュアーは差異が発生している部分しかチェックしない。</p> <p><strong>コメントが実装と違っていてもテストは通るし、人の目のチェックも通る時は通る</strong>のだ。だからこそ、コメントは常に正確に書いていなければそもそも書く意味がないのだ。コードを変えたならコメントもそれに合わせて変えなければならないのだ。</p> <p>でも人間はそんな完璧じゃないから絶対にどこかで修正漏れが発生する。だったら初めから「コードを読んだら秒でわかる」ような箇所のコメントは不要なのだ。</p> <h1 id="コードを読んだらわかるが読むのに時間がかかりそうな時は書く"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E8%AA%AD%E3%82%93%E3%81%A0%E3%82%89%E3%82%8F%E3%81%8B%E3%82%8B%E3%81%8C%E8%AA%AD%E3%82%80%E3%81%AE%E3%81%AB%E6%99%82%E9%96%93%E3%81%8C%E3%81%8B%E3%81%8B%E3%82%8A%E3%81%9D%E3%81%86%E3%81%AA%E6%99%82%E3%81%AF%E6%9B%B8%E3%81%8F">コードを読んだらわかるが読むのに時間がかかりそうな時は書く</a></h1> <p>以下のようなコード。</p> <pre><code class="csharp">public static List<string> Nabeatsu() { var nabe = new List<string>(); foreach (var n in Enumerable.Range(1, 40)) if ((n % 3 == 0) || $"{n}".Contains("3")) nabe.Add("アホ"); else nabe.Add($"{n}"); return nabe; } </code></pre> <p>これは、「1から40までの自然数のうち、3の倍数または3のつく数字の時は「アホ」を、そうでない時はその数字を文字列型のListに入れて返す」という挙動の<code>Nabeatsu</code>というメソッドである。</p> <p>上記のことは、コードを読めば分かるが意図を正確に把握するにはを全て読まなければならない。</p> <p>こういうコードは処理が簡単に書いてあれば便利だ。メソッドであればXMLコメントとして残すべきだ。</p> <p>Visual Studioを使っているならば、メソッドの上に<code>///</code>と入力するだけでXMLコメントの雛形が自動で作成される。</p> <pre><code class="csharp">/// <summary> /// /// </summary> /// <returns></returns> public static List<string> Nabeatsu() { var nabe = new List<string>(); foreach (var n in Enumerable.Range(1, 40)) if ((n % 3 == 0) ** $"{n}".Contains("3")) nabe.Add("アホ"); else nabe.Add($"{n}"); return nabe; } </code></pre> <p>あとは、コメントを書いていくだけだ。</p> <pre><code class="csharp">/// <summary> /// 1から40までの自然数のうち、3の倍数または3のつく数字の時は「アホ」を、そうでない時はその数字を文字列型のListに入れて返す /// </summary> /// <returns>そのまま使えるナベアツリスト</returns> public static List<string> Nabeatsu() { var nabe = new List<string>(); foreach (var n in Enumerable.Range(1, 40)) if ((n % 3 == 0) ** $"{n}".Contains("3")) nabe.Add("アホ"); else nabe.Add($"{n}"); return nabe; } </code></pre> <p>このようにXMLコメントを書いておくと、<br /> <a href="https://crieit.now.sh/upload_images/65effe08f1a79b8612a3b12b55d32f4d5ffedf697abff.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/65effe08f1a79b8612a3b12b55d32f4d5ffedf697abff.jpg?mw=700" alt="image" /></a><br /> のように、呼び出し元でメソッド名をマウスオーバーすると参照できるようになる。</p> <h1 id="なぜこのようなロジックになっているかを書く"><a href="#%E3%81%AA%E3%81%9C%E3%81%93%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%92%E6%9B%B8%E3%81%8F">なぜこのようなロジックになっているかを書く</a></h1> <p>コードを読んでいると、「ここはなんでこう書いてるの?」と思うことがある。その疑問に先回りして「なぜか」が書いてあるコメントは良いコメントだと思う。</p> <p>やや乱暴な例だが、例えば以下のようなコード。</p> <pre><code class="csharp">user.UpdatePasswordTo(plainPassword); </code></pre> <p>これは恐らく、「パスワードを引数の文字列で更新している」という処理だろう。</p> <p>しかし<code>plainPassword</code>は見るからに平文のパスワードだ。こんなもんそのまま更新する訳にはいかない。</p> <p>このコード、実は<code>UpdatePasswordTo</code>内部で引数の文字列はハッシュ化するという処理が実行されることになっている。だからここは別に平文で渡しても問題ないのだ。</p> <p>だがそんなことはどこにも書いてない。<code>UpdatePasswordTo</code>の実装を見るまでは分からないのである。</p> <p>そこで、</p> <pre><code class="csharp">user.UpdatePasswordTo(plainPassword); // 中でハッシュ化するから平文でOK </code></pre> <p>というコメントがあったとしたらどうだろうか。それなら問題ないな、と疑問がすぐ解決するのではないだろうか。</p> <p>もちろん、そのコメントが嘘であってはいけない(つまり本当は中でハッシュ化などしていない)が、こういうコメントはそれが事実である限りとても役に立ち、コードリーディングを助けるものになる。</p> <h1 id="拡張・修正する際に、罠になりそうな箇所の警告を書く"><a href="#%E6%8B%A1%E5%BC%B5%E3%83%BB%E4%BF%AE%E6%AD%A3%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AB%E3%80%81%E7%BD%A0%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%9D%E3%81%86%E3%81%AA%E7%AE%87%E6%89%80%E3%81%AE%E8%AD%A6%E5%91%8A%E3%82%92%E6%9B%B8%E3%81%8F">拡張・修正する際に、罠になりそうな箇所の警告を書く</a></h1> <p>これも余りいい例が思い浮かばないのでちょっと強引な例だが書いてみる。</p> <p>あるシステムがあり、利用者には個別の<code>userId</code>を自分で設定してもらう。<code>userId</code>は"@"以外の文字列で任意に設定できるが、実は使用しているライブラリのバグで"@"から始まる文字列を登録しようとすると実行時エラーになる。が、現在の仕様だとそもそも"@"は入ってこないため特に問題はなかったとする。</p> <p>ここで"@"をIDに含めたいというユーザーの要望により、ユーザーIDに"@"を含められるように仕様変更することになった。"agasahakase"というユーザーがカッコつけて"@g@s@h@k@se"というIDにしたいと言い出したのだ。</p> <p>仕様変更しリリースすると、"agasahakase"さんは"@g@s@h@k@se"にIDを変更していた。別のユーザーで、TwitterライクなIDにしたいと思い"apashoni"から"@apashoni"に変更しようとしたユーザーは更新に失敗してしまった。</p> <p>急いで原因を調査するが、何も分からない。コードを書いた人は既に転職しており誰も原因がわからない。三日三晩寝ずに調べて、とうとう"@"で始まる文字列はIDに設定できないということが判明した。</p> <p>もしここで、</p> <pre><code class="csharp">user.UpdateIdTo(newId); // 現行仕様では関係ないが、ライブラリのバグで"@"で始まるIDは登録できない </code></pre> <p>などと一言添えてあればそれを見越したリリース案内が出来たのである。</p> <p>まぁ上記のはかなり強引な一例であり実際にここまで書くかは議論の分かれるところかもしれないが、「罠になりそうあ箇所の警告を書く」とは上記のような話だ。</p> <p>現行仕様や近々に何かに影響する訳ではないが、将来的に役立つかもしれないことを書いておくのも良い。</p> <p>繰り返すが上記はかなり強引な例えだ(いい例が思いつかなかった)。</p> <h1 id="コメントで説明するくらいなら命名を見直す"><a href="#%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%81%A7%E8%AA%AC%E6%98%8E%E3%81%99%E3%82%8B%E3%81%8F%E3%82%89%E3%81%84%E3%81%AA%E3%82%89%E5%91%BD%E5%90%8D%E3%82%92%E8%A6%8B%E7%9B%B4%E3%81%99">コメントで説明するくらいなら命名を見直す</a></h1> <p><a href="https://crieit.net/posts/csharp-naming">【C#】命名って大事だね</a>という記事でも書いたが、不足情報を補うくらいなら命名やロジックで直感的に説明しコメントは書かないという方がよほど親切だ。理由は前述した通り、コメントもメンテナンスが必要になるため。</p> <p>例えば以下のようなコード。</p> <pre><code class="csharp">// 単価 decimal price = 100; // 単位はmm decimal height = 1700; </code></pre> <p>これらは</p> <pre><code class="csharp">decimal unitPrice = 100; decimal height_mm = 1700; </code></pre> <p>という命名にすれば、単価だということや単位がmmだということは一目瞭然だ。コメントを書く前に、まずこれらができないか試すべきだと個人的には思う。</p> <h1 id="変更前のソースをコメントアウトして残さない(論外)"><a href="#%E5%A4%89%E6%9B%B4%E5%89%8D%E3%81%AE%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%92%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%82%A2%E3%82%A6%E3%83%88%E3%81%97%E3%81%A6%E6%AE%8B%E3%81%95%E3%81%AA%E3%81%84%EF%BC%88%E8%AB%96%E5%A4%96%EF%BC%89">変更前のソースをコメントアウトして残さない(論外)</a></h1> <p>これ、最近のエンジニアさんはおとぎ話くらいに思うのだろうか…?</p> <p>これらは、バージョン管理ソフトが普及していなかった頃の名残だ(と思う)。昔はバージョン管理ソフトなんていう便利なものはなかったので、こうやって修正前のコードを残しておく必要があった。</p> <p>しかし現在はだいたいどのチームでもgitやSubVersionなんかを使ってバージョン履歴管理やソースコードの共有などをしているのであり、現代ではほとんど不要なハックと言える。読んでいて邪魔になるだけだし、そもそもコメントアウトを外してもまともに動作しない。</p> <p>残念ながら未だにこういうコードは見かけるし、こういう風にコメントを残す人もいる。特に大昔からコード書いている人なんかは、よくこういうコメントアウトをしていらっしゃる。恐らくバージョン管理ソフトの使い方などを分かっていないんだと思うが、だったら勉強とかちゃんとしてほしいなと正直思う。勉強できない古のエンジニアはとっとと解雇して私の給料増やしてちょと思うのだがなかなかそうもいかないので難しいところだ。</p> <h1 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h1> <p>以上が、私がコメントを書くときに気を付けているような内容だ。ここには書いていないが意識していることも多分あると思う。</p> <p>繰り返しになるが、あくまで私個人の考えで合ってこれが正しいという訳ではないが、まぁ別にそこまで変なことを書いているつもりもないので参考になるところをつまみ食いで参考にしてもらえればいいなと思う。</p> あぱしょに tag:crieit.net,2005:PublicArticle/16578 2021-01-11T21:48:56+09:00 2021-01-11T21:48:56+09:00 https://crieit.net/posts/csharp-dry-oaoo 【C#】DRYとOAOO <h1 id="DRY原則とは"><a href="#DRY%E5%8E%9F%E5%89%87%E3%81%A8%E3%81%AF">DRY原則とは</a></h1> <p>知っている人も多いと思うが、<a target="_blank" rel="nofollow noopener" href="https://ja.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY原則</a>というものがある。</p> <p><strong>D</strong>on't <strong>R</strong>epeat <strong>Y</strong>ourselfの頭文字をとった言葉で、簡単に言うと「同じことを繰り返すな」という意味。</p> <h1 id="サンプルコード"><a href="#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89">サンプルコード</a></h1> <p>例を出してみる。</p> <pre><code class="csharp">public class Person { public string FirstName { set; get; } = ""; public string LastName { set; get; } = ""; public string FullName { set; get; } = ""; } </code></pre> <p>上記のような<code>Person</code>クラスのインスタンスを作成するとしよう。</p> <pre><code class="csharp">var haruki = new Person(); haruki.FirlstName = "Haruki"; haruki.LastName = "Yachizaki"; haruki.FullName = "Yachizaki Haruki"; Console.Write(haruki.FullName); // 結果 -> Yachizaki Haruki </code></pre> <p>FullNameを出力すると、"Yachizaki Haruki"となる。</p> <p>上記のクラスには問題がある。</p> <p>それは、<code>FirstName</code>と<code>LastName</code>を設定して、<code>FullName</code>の設定が漏れていた場合に、<code>FullName</code>が出力されないという問題だ。</p> <pre><code class="csharp">var haruki = new Person(); haruki.FirstName = "Haruki"; haruki.LastName = "Yachizaki"; // haruki.FullName の設定を忘れている Console.Write(haruki.FullName); // 結果 -> ""(空白) // PersonクラスのFullNameのデフォルト値が表示される </code></pre> <p>設定されるべき値を設定していなかったのだから当然の挙動だが、そもそも一般的に<code>FullName</code>は<code>FirstName</code>と<code>LastName</code>さえ分れば求められるにも関わらず、個別に設定しなければならない方がおかしいと言えるだろう。<code>FullName</code>の設定を繰り返しているとも言える。</p> <p>そこで、<code>FullName</code>を修正し、以下のようにしてみる。</p> <pre><code class="csharp">public class Person { public string FirstName { set; get; } = ""; public string LastName { set; get; } = ""; public string FullName => $"{LastName} {FirstName}"; } </code></pre> <p><code>FullName</code>は個別に設定するのではなく、<code>FirstName</code>と<code>LastName</code>を組み合わせて返すように変更する。</p> <p>すると、</p> <pre><code class="csharp">var haruki = new Person(); haruki.FirstName = "Haruki"; haruki.LastName = "Yachizaki"; // haruki.FullName は設定しない(setterを持たないのでそもそもできない) Console.Write(haruki.FullName); // 結果 -> Yachizaki Haruki </code></pre> <p>となる。</p> <p>他のプロパティから求められるプロパティは個別に用意しないという考え方では、DB設計などでも用いられる。DB設計においては、主にパフォーマンスの面から冗長なフィールドを用意することもあるが(<code>価格</code>と<code>税率</code>と<code>税込み価格</code>を持っておくなど)、プログラミングのソースコードにおいてはそこまで意識することは少ないと言えると思う(※ぱっと例が思いつかないが、冗長な実装をした方がいいケースもきっとあると思う)。</p> <p>プロパティが増えれば増えるほど管理しなければいけない情報が増え、バグの元になる。</p> <h1 id="メリット・デメリット"><a href="#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%83%BB%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88">メリット・デメリット</a></h1> <p>メリット</p> <ul> <li>テストの箇所を集約できる <ul> <li>複数個所に書いていればその分テストが必要だが、一か所であればそれだけでカバーできる</li> </ul></li> <li>ロジックの改善や仕様変更の際に修正の手間が激減する <ul> <li>トレースログを仕込む時などに便利</li> </ul></li> </ul> <p>デメリット</p> <ul> <li>変更が呼び出し箇所全てに反映されるため、影響範囲を把握しておく必要がある</li> </ul> <h1 id="OAOO"><a href="#OAOO">OAOO</a></h1> <p>DRY原則とよく似た考え方に、OAOO(<strong>O</strong>nce <strong>A</strong>nd <strong>O</strong>nly <strong>O</strong>nce:ただ一度だけ書く)がある。</p> <p>例を示す。下記のようなコードがあるとする。</p> <pre><code class="csharp">var message1 = "あけましておめでとうございます"; var message2 = "今年もよろしくお願いします。"; var newMessage1 = ""; var newMessage2 = ""+ const string Dot = "。"; if (message1.EndsWith(Dot)) newMessage1 = message1; else newMessage1 = message1 + Dot; if (message2.EndsWith(Dot)) newMessage2 = message2; else newMessage2 = message2 + Dot; Console.Write(newMessage1 + newMessage2); // 結果 -> あけましておめでとうございます。今年もよろしくお願いします。 </code></pre> <p>上記コードは2つのメッセージを連結して出力するが、各メッセージが読点(<code>。</code>)で終わっていなければ付け足した後に連結するということをしている。</p> <p>この、「読点がなければ付け足す」という処理は<code>message1</code>に対して行うか<code>message2</code>に対して行うかだけの違いだが、2回に渡って書かれている。</p> <p>これにOAOOを当てはめると、以下のようにできる。</p> <pre><code class="csharp">// 以下のメソッドを用意 static string AppendDotIfNeeded(string message) { const string Dot = "。"; // nullチェックは省略 if (message.EndsWith(Dot)) return message; else return message + Dot; } // メソッドを用意すると以下のように書ける var message1 = "あけましておめでとうございます"; var message2 = "今年もよろしくお願いします。"; var message1EndsWithDot = AppendDotIfNeeded(message1); var message2EndsWithDot = AppendDotIfNeeded(message2); Console.Write(newMessage1 + newMessage2); // 結果 -> あけましておめでとうございます。今年もよろしくお願いします。 </code></pre> <p>「読点がなければ付け足す」という処理をメソッドに抽出したことで流用できるようになった。</p> <p>DRYはシステム全体での重複を(排除すべきところでは)排除しようという考え方、OAOOはあくまでソースコード上において、同じような内容はまとめようという考え方だと理解している。</p> あぱしょに tag:crieit.net,2005:PublicArticle/16572 2021-01-09T22:31:27+09:00 2021-06-03T20:45:52+09:00 https://crieit.net/posts/csharp-naming 【C#】命名って大事だね <p>命名って大事だよね、ということはコードを書く人であればだいたい同意していただけると思う。</p> <p>というかコードを書かない人も「memo.txt」と「〇月〇日までに買う予定リスト.txt」だったら、ファイルの内容が同じでも後者の方が圧倒的にわかりやすいとは思っていただけると思う。</p> <p>毎度毎度弊社の困ったちゃんのことを書くのは忍びないが、だけど書くが、困ったちゃんははっきり言って命名がヘタクソである。私も別に命名に自信ニキという訳ではないが、まぁ困ったちゃんよりは上手く命名していると思うし、自分の命名で困ったこともあまりないので書いてみる。</p> <p>以降、サンプルコードにC#を用いるが別にどの言語でも共通する話だと思う。難しいことは書かないのでC#がわからなくてもだいたい読めると思う。</p> <h1 id="なぜ命名が大事か"><a href="#%E3%81%AA%E3%81%9C%E5%91%BD%E5%90%8D%E3%81%8C%E5%A4%A7%E4%BA%8B%E3%81%8B">なぜ命名が大事か</a></h1> <p>簡潔に言うと情報量の違いだと思う。</p> <p>極端な例だが、次のような変数宣言があるとする。</p> <pre><code class="csharp">decimal price = 100; </code></pre> <p><code>price</code>は価格・値段といった意味だが、はっきり言って<code>price</code>という文字だけでこれが何に使われるのか正確にはわからない。</p> <p>具体的には以下のような情報が欠けている。</p> <ul> <li>単価?小計?合計?</li> <li>税込み?税抜き?</li> <li>(キャンペーンなどがある場合)割引適用前?適用後?</li> <li>単位は日本円?ドル?</li> </ul> <p>こういった情報はできるだけ変数名に明示的に盛り込むべきだと考える。</p> <pre><code class="csharp">// 単価なら decimal unitPrice = 100; // 小計なら decimal subTotal = 100; // 合計なら decimal total = 100; // 税込みなら decimal taxIncludedPrice = 100; // 税抜きなら decimal taxExcludedPrice = 100; // 割引適用前なら decimal undiscountedPrice = 100; // または originalPrice // 割引適用後なら decimal discountedPrice = 100; // 単位が縁 decimal price_yen = 100; // 単位がドル decimal price_dol = 100; </code></pre> <p>といった具合に変数名に情報量を持たせることで可読性を上げることができる。</p> <p>この考え方は一部、アプリケーションハンガリアンといわれる考え方と一致する。</p> <p>たとえば、</p> <pre><code class="csharp">decimal total = price_yen + price_dol; </code></pre> <p>のようなコードはドルと日本円を加算しており、明らかに間違いだということが<strong>見ただけで</strong>分る。正しくは</p> <pre><code class="csharp">// ドルは円に換算して可算する decimal total = price_yen + ConvertToYen(price_dol); </code></pre> <p>としなければならないと判断できる。これが命名が持つ強力なメリットであり、命名にこだわる理由である。</p> <p>こういった考え方が活きる場面はたくさんある。</p> <pre><code class="csharp">// パスワード string password = "XXXXX"; // パスワードを更新 user.updatePassword(password); </code></pre> <p>これだと、<code>password</code>で更新しているが、うっかり<code>password</code>が平文のままだったら平文がそのまま登録されているかもしれない。</p> <p>もし変数名を<code>plainPassword</code>などとしていれば平文のパスワードということが見ただけで分かるので、登録前にハッシュ化させる必要があると気づけるだろう。</p> <pre><code class="csharp">// 平文のパスワード string plainPassword = "XXXXX"; // ハッシュ string hashedPassword = plainPassword.Hash(); // ハッシュ化されたパスワードで更新 user.updatePassword(hashedPassword); </code></pre> <p>また、コーディングミスにより</p> <pre><code class="csharp">// 誤って平文で更新するコードになっている user.updatePassword(plainPassword); </code></pre> <p>と書いてしまっていたとしても、「平文で更新するっておかしいよね?」と気づくきっかけになるハズだ。</p> <p>このような「これは税計算必要なの?」「これは平文?」などの情報はよくコードを読めば分かることではある。だがその「よくコードを読む」作業を意識から切り離して、本来考えたいアルゴリズムや可読性などに集中できるのが大事だ。そしてそれは命名の工夫をするだけで改善できることでもある。</p> <p>汎用性の高い接頭辞や接尾辞もあるので、それらはいつでも使えるようになっておくとベストだ。</p> <h1 id="xxxFlgという変数名"><a href="#xxxFlg%E3%81%A8%E3%81%84%E3%81%86%E5%A4%89%E6%95%B0%E5%90%8D">xxxFlgという変数名</a></h1> <p>真偽値などで<code>xxxFlg</code>などという命名をしているのをたまに見かけるが、これもあまり優しくないと思う。</p> <p>例えば<code>deleteFlg</code>という変数名があるとする。これは以下のように様々な解釈が可能である。</p> <ul> <li>削除済みのデータであることを示すフラグ</li> <li>削除できる状態のデータであることを示すフラグ</li> <li>削除しなければならないデータを示すフラグ</li> <li>削除される予定のデータであることを示すフラグ</li> </ul> <p>などだ。<code>delete</code>としか書かれていないのだから如何様にも解釈できる。<code>true</code>で削除済みなのか<code>false</code>で削除済みなのかも、変数名からは分からない。個人開発ならともかく、チームで開発するプロジェクトにおいて「そんなつもりで命名した訳じゃない」「普通に考えたらこう」なんていうのは通用しない。何故ならそのコードは自分だけではなく、他の誰かが読んだり修正したりするかもしれないからだ。個人開発だとしても、何日も経って忘れたころに見直すこともあるだろう。だからこそ、直感的に分かりやすい命名をする必要がある。</p> <p>真偽値の命名には<code>is</code>, <code>has</code>, <code>can</code>(もしくは<code>is~able</code>), <code>should</code>などを使うと可読性が上がると言われている。それらはY/N質問として読めるし、意味のはき違えようがないからだ。</p> <pre><code class="csharp">// 削除済み bool isDeleted = true; // 削除できる bool canDelete = true; bool isDeletable = true; // 削除しなければならない bool shouldDelete = true; </code></pre> <p>これだと、<code>isDeleted</code>は「削除済みか?」に対して<code>true</code>(削除済み)か<code>false</code>(削除済みではない)とハッキリするのである。<code>isDeleted</code>という変数名で「<code>true</code>だから『削除しなければならない』ってことだな!」「<code>true</code>だから未削除なんだな!」と解釈する人はまずいないだろう。それは考え方とかじゃなくて英語力の問題だから…。</p> <h1 id="コメントで補えるのでは"><a href="#%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%81%A7%E8%A3%9C%E3%81%88%E3%82%8B%E3%81%AE%E3%81%A7%E3%81%AF">コメントで補えるのでは</a></h1> <p>命名をシンプルにしてコメントで補えるのでは、と思うかもしれない。確かにそういう手もあるが、個人的には望ましくないと考える。なぜか。</p> <p>それはコメントはメンテしないといけないからだ。</p> <pre><code class="csharp">// 税抜き価格 decimal price = 100; </code></pre> <p>というコメントをつけたコードがあったとする。これが税込み価格を反映するという修正が必要になった場合、</p> <pre><code class="csharp">// 税抜き価格 decimal price = 110; </code></pre> <p>と修正するだけでなく、コメントも</p> <pre><code class="csharp">// 税込み価格 decimal price = 110; </code></pre> <p>と直さなければならなくなる。修正の工数がしっかり確保されており、コメントも含めてレビューされるような環境であればまだいいかもしれないが、多くの場合修正レビューはテストが通るかどうかと差分の比較であり、コメントは忘れ去られる。動作は自動テストが保障してくれるかもしれないが、コメントが合っているかどうかは人の目でみないと分からない。</p> <p>もしコメントのメンテを怠ると、そのコメントは嘘になる。コメントに嘘が書いてあるくらいなら、コメントがない方が100倍ましだ。そうやって嘘のコメントが積み重なって保守不可能な過去の遺産になっていく。コメントで意味を補足するくらいなら、<code>taxExcludedPrice</code>や<code>taxIncludedPrice</code>などの具体的な意味を持った命名をした方が良い。</p> <h1 id="システムハンガリアンは…"><a href="#%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%83%8F%E3%83%B3%E3%82%AC%E3%83%AA%E3%82%A2%E3%83%B3%E3%81%AF%E2%80%A6">システムハンガリアンは…</a></h1> <p>前述した「アプリケーションハンガリアン」とは別に「システムハンガリアン」という考え方もあるが、これは現代ではもはや推奨されていないシーンの方が多い。以前は私も使っていたが、最近はまず使わないようになった。</p> <pre><code class="csharp">string sName = "あぱしょに"; int nAge = 27; </code></pre> <p>システムハンガリアンは、<code>string</code>型なら<strong>s</strong>や<strong>str</strong>、int型なら<strong>n</strong>や<strong>int</strong>のように、各変数の型を識別できる接頭辞を入れるというものだ。</p> <p>これも同様にコードを見ただけでエラーが分かるようになるというハックの一つだが、静的型付け言語ではたとえば</p> <pre><code class="csharp">string sName = "あぱしょに"; int nAge = 27; int hoge = nAge * sName; // エラー </code></pre> <p>などと間違えて書いても<br /> <a href="https://crieit.now.sh/upload_images/9efd38256758a1d84d90e3d5578cfd715ff9b00d04cd3.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9efd38256758a1d84d90e3d5578cfd715ff9b00d04cd3.jpg?mw=700" alt="image" /></a><br /> のように教えてくれるので、変数を見ただけで型の不一致がわかるというメリットは少ない。動的型付け言語であれば違うと思うが…。</p> <p>また、システムハンガリアンは型を変更した際に変数名も修正しなければならない(そうでないとシステムハンガリアンのメリットが正しく発揮されない)。たとえば<code>nUserId</code>を<code>int</code>型から<code>string</code>型に変更した場合は、型だけでなく変数名も<code>sUserId</code>と変更しなければならず、これは大変な手間である。</p> <p>そういった理由で、システムハンガリアンは現代ではほとんど見られなくなった(少なくとも私の観測範囲では)。これからも私が積極的に使うことはないだろう。昔の案件の修正などで既にコーディングスタイルが指定されていれば従うが。</p> <h1 id="英語にこだわらなくていい"><a href="#%E8%8B%B1%E8%AA%9E%E3%81%AB%E3%81%93%E3%81%A0%E3%82%8F%E3%82%89%E3%81%AA%E3%81%8F%E3%81%A6%E3%81%84%E3%81%84">英語にこだわらなくていい</a></h1> <p>個人的には無理して英語にこだわって意味不明な変数名になるよりは、別にローマ字でもいいから意味が分かるよう正確に命名してほしいと思っている。</p> <p>また、英語に自信がなければ<a target="_blank" rel="nofollow noopener" href="https://codic.jp/">codic</a>や<a target="_blank" rel="nofollow noopener" href="https://www.deepl.com/translator">DeepL</a>など便利なサービスもあるので、それらも活用したい。特に前者はネーミングに特化しているだけでなく、<code>camelCase</code>や<code>snake_case</code>、<code>PascalCase</code>など自由にスタイルをカスタマイズできる。私はこれらのサービスで色んな語を知った。</p> あぱしょに tag:crieit.net,2005:PublicArticle/16567 2021-01-08T21:12:03+09:00 2021-01-08T21:12:03+09:00 https://crieit.net/posts/csharp-expression-bodied 【C#】ワンライナーで書ける式形式メンバー <h1 id="式形式メンバー"><a href="#%E5%BC%8F%E5%BD%A2%E5%BC%8F%E3%83%A1%E3%83%B3%E3%83%90%E3%83%BC">式形式メンバー</a></h1> <p>まずは下記のコードをご覧ください。</p> <pre><code class="csharp">public static bool IsNullOrEmpty(this string text) { return string.IsNullOrEmpty(text); } </code></pre> <p>上記は<a target="_blank" rel="nofollow noopener" href="/2020/12/30/csharp-extension-methods/">【C#】拡張メソッド</a>という記事で例示した、<code>string.IsNullOrEmpty()</code>を扱いやすくした拡張メソッドです。</p> <pre><code class="csharp">var text = ""; // これが Cnosole.Write(string.IsNullOrEmpty(text)); // こう書ける Console.Write(text.IsNullOrEmpty()); </code></pre> <p>という方法を実現する拡張メソッドですね。</p> <p>このコード、<code>string.IsNullOrEmpty()</code>を<code>return</code>しているだけなのに<code>{}</code>で括ってあげるのがなんか嫌じゃないですか?</p> <p>だって、<code>foreach</code>も<code>if</code>も、続く処理が単文(単一ステートメント)であれば<code>{}</code>は不要ですよね。</p> <pre><code class="csharp">// これは foreach (var n in Enumerable.Range(1, 20)) { Console.Write(n); } // こう書ける foreach (var n in Enumerable.Range(1, 20)) Console.Write(n); // これは if ((n == 3) || ($"{n}".Contains(3))) { Console.Write("アホ"); } // こう書ける if ((n == 3) || ($"{n}".Contains(3))) Console.Write("アホ"); </code></pre> <p>組み合わせて</p> <pre><code class="csharp">// これを foreach (var n in Enumerable.Range(1, 20)) { if ((n == 3) || ($"{n}".Contains(3))) { Console.Write("アホ"); } } // こう書ける foreach (var n in Enumerable.Range(1, 20)) if ((n == 3) || ($"{n}".Contains(3))) Console.Write("アホ"); </code></pre> <p>こうも書ける訳です。余計な<code>{}</code>がなくてスッキリしていますよね。特に先人の残した<strong>ネスト地獄</strong>のコードを読んでいると、<code>{}</code>なんて見るのも嫌じゃないですか。</p> <p>だから、メソッドでも<code>{}</code>なしで書きたいですよね?ですよね?</p> <p>メソッドも、<code>{}</code>を省略して書けるケースがあります。</p> <pre><code class="csharp">// これは public static bool IsNullOrEmpty(this string text) { return string.IsNullOrEmpty(text); } // こう書ける public static bool IsNullOrEmpty(this string text) => string.IsNullOrEmpty(text); </code></pre> <p>どうでしょうか?<code>{}</code>が減っただけですが、かなりスッキリしましたよね。</p> <p>こういう記法ができる式形式メンバーは<a target="_blank" rel="nofollow noopener" href="https://docs.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-version-history">C#6.0で実装され、C#7.0で拡張されました。</a></p> <h1 id="条件"><a href="#%E6%9D%A1%E4%BB%B6">条件</a></h1> <p>式形式メンバーは、単一ステートメントで記載されているメソッドやプロパティに使用できます。</p> <p>なので、たとえば以下のようなメソッドは、式形式メンバーは使用できません。</p> <pre><code class="csharp">// アホ毛・パーカー・ショートヘア・ニーソのいずれか2つ以上を満たせばボーイッシュとする public static bool IsBoyish(this GirlModel girl) { var boyishibility = 0; // アホ毛か if (girl.HasAhoge) boyishibility++; // パーカーか if (girl.IsWearingHoodie) boyishibility++; // ショートヘアか if (girl.HasShortHair) boyishibility++; // ニーソか if (girl.IsWearingKneeSocks) boyishibility++; // 判定 return (boyishibility >= 2); } </code></pre> <p>ですが、たとえばボーイッシュがより広く浸透した世界で、アホ毛・パーカー・ショートヘア・ニーソのいずれか一つでも満たせばボーイッシュといえるようになった場合は、下記のように書けます。</p> <pre><code class="csharp">public static bool IsBoyish(this GirlModel girl) => (girl.HasAhoge || girl.IsWearingHoodie || girl.HasShortHair || girl.IsWearingKneeSocks); </code></pre> <p>ちなみにアホ毛・パーカー・ショートヘア・ニーソは私のHN「あぱしょに」の<a target="_blank" rel="nofollow noopener" href="/2020/12/01/renamed/">名前の由来</a>です(小声)</p> <h1 id="書き方"><a href="#%E6%9B%B8%E3%81%8D%E6%96%B9">書き方</a></h1> <p>書き方は、<code>{}</code>の代わりに<code>=></code>を使用して、<code>return</code>を省略するという記法になります。</p> <pre><code class="csharp">// これは× // returnは書かない public static bool IsNullOrEmpty(this string text) => return string.IsNullOrEmpty(text); </code></pre> <p>この記法は、続くステートメントを<code>return</code>しますよ、ということをコンパイラに通知しているんですね。なので明示的に<code>return</code>は書けません。</p> <p><code>{}</code>を省略<strong>できる</strong>と書きましたがどちらかというと副産物的なメリットで、本来は<code>return</code>を省略するための記法ということになります。</p> <h1 id="戻り値を返さないメソッドにも使える"><a href="#%E6%88%BB%E3%82%8A%E5%80%A4%E3%82%92%E8%BF%94%E3%81%95%E3%81%AA%E3%81%84%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AB%E3%82%82%E4%BD%BF%E3%81%88%E3%82%8B">戻り値を返さないメソッドにも使える</a></h1> <p>戻り値を返さないメソッドに対しても、単一ステートメントのメソッドであれば式形式メンバーを使用できます。</p> <pre><code class="csharp">// これは public static void WriteToConsole(this object logMessage) { Console.Write(logMessage); } // こう書ける public static void WriteToConsole(this object logMessage) => Console.Write(logMessage); </code></pre> <p>これらのメソッドはもともと、ふつうは<code>return</code>を省略するかと思いますが式形式メンバーでも同様に<code>return</code>は書きません。</p> <h1 id="式形式メンバーは便利か"><a href="#%E5%BC%8F%E5%BD%A2%E5%BC%8F%E3%83%A1%E3%83%B3%E3%83%90%E3%83%BC%E3%81%AF%E4%BE%BF%E5%88%A9%E3%81%8B">式形式メンバーは便利か</a></h1> <p>個人的には、使えるところでは積極的に使っています。タイプ量が減るのも良いですが、ワンライナーで書けるのがやっぱり楽です。慣れてしまえば読む時でもメリットがあると思います。</p> <p>ただし、実際の処理が改行&インデントされていれば、それはそれで読みやすいということもあると思います。その辺りは個人の感覚によりけりですが、こういう記法があるということを知っているだけでも訳に立つと思います。</p> <h1 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://docs.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-version-history">C# の歴史</a><br /> <a target="_blank" rel="nofollow noopener" href="https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members">式形式のメンバー (C# プログラミング ガイド)</a></p> あぱしょに