【自作PC】購入用メモ【順次更新】

組む時期

増税直前ということで9月頃を予定しています。

メインパーツ

個人的な優先度順で書きます。

ケース

まだ決めきっていませんが、A4-SFXを選ぼうと思っています。
理由は、今回の自作で求めるのが最もコンパクトなケースであることだからです。

kakaku.com

個人的にはSilver StoneのSG-13の後継とかを何年も期待してるんですが、残念ながらそのような製品は話題にすら上がらず……。

一応その他候補ケースはこちらにまとめてあります。 wrongwrong163377.hatenablog.com

CPUクーラー

CPUクーラーはCryorig C7Gにするつもりです。
小型ながら圧倒的な冷却力、メモリに制限が無いロープロファイルヒートシンクならこれが一番優秀だと思ってます。
未発売で組みたい時期に間に合ってくれるかが不明なことと、CPUを冷やしきれるかが問題……。

まだ内容が入っていませんが、一応公式サイトも既に有るみたいですね。

www.cryorig.com

A4-SFXにはほぼ専用な簡易水冷クーラーも有るんですが、個人的に簡易水冷はもう飽きたので今度は空冷にするつもりです。

CPU

Ryzen 9も考えましたが、スペックを大きく求める場面がゲーム用途かつ流石にそこまでパワーは必要無いだろうということでRyzen 7 3800Xにしようと思います。
今使っているのがIntel Core i7 6700なので、それにしたってものすごいパワーアップなんですが。
ただ、仮にC7Gで3800Xが冷やしきれないということであれば、その時は3700Xまで落とすかもしれません……。

kakaku.com

メモリ

G.Skill Trident Z Neoシリーズから選ぶつもりです。
本音を言うとDDR4 3600 C14とかいう超スペックなやつを選びたいんですが、16 x 2キットは今の所発表されてないみたいなんで、16 x 2キット中一番良スペックなものを選ぶつもりです。

blog.livedoor.jp

グラフィックボード

まだ出ていないですが、CPUに合わせてRadeon 5000シリーズの上位機種を考えています。
ただ、まだまだ情報が出揃っていないことも有るので、もしかするとRTX 2080Tiとかにせざるを得ないかもしれませんね。
Radeon 5000シリーズはPCIe 4.0に対応しているものの、現状のGPUの性能ではPCIe帯域がボトルネックになることは少なかったはずなので、実際はそこまで重視しなくてもいいのかなとは思っています。

ただ、2スロット高性能グラボって今本当に少ないんですね……。
見た感じINNO3DGEFORCE RTX 2080 TI GAMING OC X3が一番良さそうな位で、「マザボも作ってるメーカーのものは大概2スロ = そこまで冷却力有るモデル無し」になってしまっているのが残念です。
自分が自作に触れた頃はGigabyteが2スロ3連ファンって印象が強かったんですが、、、。

マザーボード

グラフィックボードに合わせて選ぶか、合わせてもいいことが無さそうなら良さげなのをそのまま選ぶつもりです。
なのでGPUを決めるまで保留します。

一応ASUSのROG Crosshair VIII Impactが気になってはいるんですが、A4-SFXだとサイズ的に積めないだろうなあという辛さが……。

www.asus.com

電源

小型ケースなこともあり、SF750 Platinumが安定かなと思います。

kakaku.com www.tomshardware.com

SSD

使い回しで960 PRO M.2 MZ-V6P1T0B/ITです。

kakaku.com

その他パーツ

オプショナルなパーツ類です。

ケースファン

A4-SFXでは底部に92ミリ角ファンを積めるので、厚い方はNF-B9 redux-1600を入れようかなと思っています。
正直これを選ぶ理由もそこまで無いんですが、Noctua製だし色も悪くないと来ればこれが安定かな、と。

薄い方は何を入れようかな……。

kakaku.com

CPUクーラーファン

C7Gを光らせる用です。
A4-SFXで光らせる必要性は薄いと思っていますが、光がいい感じに抜けるようであれば積んでもいいかなと思っています。

www.links.co.jp

【SpringBoot】内部エラー周りの話

内部エラー周りの設計について自分の経験から得た知見をまとめます(なのでセオリーとかアンチパターンとか有れば教えていただけるとありがたいです)。
内部エラーとは基本的に自分で書いてThrowするようなエラーを想定しています。

エラーハンドリングに関してはサンプル記事が溢れているので省略します。

例外クラスの作り方

サーバーとフロント側で「エラー内容/HTTPステータスコードによって大体の挙動を統一する」ことができるため、基本的に返却するHTTPステータスコードに合わせて例外クラスを作ればよいと思います。
内部エラーコードを設定することも考えられますが、アプリケーション規模が小さいうちはそこまでしなくてもHTTPステータスコードに合わせておけば大体の場合に対応できるので、個人的にはYAGNIかなと思っています。

自分のやっているプロジェクトでは以下のような例外クラスを設定していました(抜粋です)。

ステータスコード 例外クラス名 エラー内容 フロントでの対応
400 InvalidFormException フォームの入力エラー 項目ごとにエラー表示
409 ResourceConflictException リソース更新のコンフリクト データの再取得を促すアラートを表示
500 ${プロジェクト名}Exception その他内部的なエラー エラーページの表示

継承元に関してはExceptionではなくRuntimeException系のものを設定した方が後々楽だと思います(ラムダ式内で内部エラーを投げる時に困る場合などが有るため)。

その他Tips的な内容

スタックトレースのフィルタリング

全て1つのプロジェクトで完結している場合、内部エラーは発生箇所がパッケージ内に有ることが確実になるため、それ以外のスタックトレースは基本的に不要となります。
そこで自分はフィルタリング関数を用意して宣言時にスタックトレースを設定し直していました。

フィルタリング関数

static StackTraceElement[] filteringStackTrace(StackTraceElement[] elements) {
    return Arrays.stream(elements)
            .filter(it -> it.getClassName().startsWith("${プロジェクトルートのパッケージ名の文字列}"))
            .toArray(StackTraceElement[]::new);
}

使い方

public class ResourceConflictException extends RuntimeException {
    public ResourceConflictException(String msg) {
        super(msg);

        // スタックトレースはフィルタリングして設定
        setStackTrace(FilteringStackTrace.filteringStackTrace(getStackTrace()));
    }
}

例外処理の結果でJSONを返す場合にJSON以外を返すControllerでproducesを設定してはならない

producesで指定したのと違う内容を返却しようとすることになるため、HttpMediaTypeNotAcceptableExceptioとしてエラーになります。
具体的には以下の記事にまとめてあります。

【Maven】OWASP Dependency CheckでsuppressionFileを指定した際に「要素'suppressions'の宣言が見つかりません。」とエラーになる問題への対処

問題

以下のようにSuppressionFileとpomを用意して抑制設定を行いました。

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
  <!-- 省略 -->
</suppressions>
<!-- 省略 -->

<plugin>
    <groupId>org.owasp</groupId>
    <artifactId>dependency-check-maven</artifactId>
    <version>5.0.0</version>
    <configuration>
        <failBuildOnCVSS>8</failBuildOnCVSS>
        <suppressionFiles>
            <suppressionFile>owasp-dependency-check-suppressions.xml</suppressionFile>
        </suppressionFiles>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>

<!-- 省略 -->

すると以下のようなエラーになりました。

  • エラー内容(抜粋)
[WARNING] Unable to parse suppression xml file 'owasp-dependency-check-suppressions.xml'
[WARNING] org.owasp.dependencycheck.xml.suppression.SuppressionParseException: org.xml.sax.SAXException: Line=2, Column=99: cvc-elt.1.a: 要素'suppressions'の宣言が見つかりません。
[ERROR] Exception occurred initializing Vulnerability Suppression Analyzer.

対処

xmlnsに指定しているdependency-suppressionのバージョンを1.2に落とせば通りました。
原因は一旦調べていません。

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.2.xsd">
  <!-- 省略 -->
</suppressions>

【Vue.js】オブジェクトの内容を変更しているのにcomputedが変化しない状況への対処

状況

dataに用意したオブジェクトの内容を変更しているのにcomputedが変化しなくて困っていました。

対処

前提

dataに宣言する時点でプロパティを宣言しておけばVueが更新を追ってくれるので、基本はプロパティを宣言しておいた方がいいらしいです。

// ダメなやり方
data() {
  return {
    hogeObject: {}
  }
}

// いいやり方
data() {
  return {
    hogeObject: {
      fugaKey: null
    }
  }
}

今回の場合

初めからプロパティを宣言できない場合、$setを使うとできます。

// 改善前
this.hogeObject[fugaKey] = piyoValue

// 改善後
this.$set(this.hogeObject, fugaKey, piyoValue)

参考にさせていただいたサイト

【自作PC】全高47mm以上66mm以下でTDP100W以上のトップフローロープロファイルCPUクーラー比較

自作用の調査まとめです(なので完璧な網羅性は期待しないでください、、、久々の自作で練度が落ちてるのです。。。)。
単位はmmまたはWに統一しています。

CPUクーラーの性能はメーカー発表のものなので必ずしも正確に比較できるとは限りません。正確性を求めるなら個々のクーラーの比較レビューを地道に漁っていくしか無いと思います。
というかファン変更とか考えるとCPUクーラーの性能って本当に変動しちゃうので比較は難しいです。
日本で手に入らなかったり現状手に入らなかったりするものも載せてるかもしれません。

選抜基準はCryorig C7(47mm)以上、66mm(GHOST S1 MkIIに搭載可能な最大サイズ)以下です。また、同一シリーズで性能が低いものは基本載せていません。

名前 高さ ファン厚 TDP 備考
C7 Cu 47 15 115
C7G 47 15 125 92mm or 120mm径の25mm厚ファンに付け替え可
AXP-100 Full Copper 62 14 180 寸法的にヒートシンク付きメモリはほぼ装着不可
Black Ridge 47 0 95 下にファンを付けるタイプ
上に140mmファンを盛れるので掲載
最大メモリ高33mm
Gabriel 60 20 100
SHADOW ROCK LP 75 25 130 15mmファンなら66mmを切るため掲載
NH-L9x65 65 14 TDPは100程度?
NH-L9x65 SE-AM4 65 14 AM4ソケット向け
SLIMHERO 59 15.8 136

感想

TDPで比較しようと思うとやっぱり厳しいんだなと再確認しました(方々のレビューを見ると多分入れ替わってそうなのがチラホラ……)。
メモリ制約無しで一番期待できそうなのはC7Gですかねーやっぱ。とりあえずC7Gの性能に期待してます。

参考にさせて頂いたサイト

【自作PC】容積12L未満でフルサイズGPUが積める小型PCケース比較 2019【Mini-ITX】

自作用の調査まとめです(なので完璧な網羅性は期待しないでください、、、久々の自作で練度が落ちてるのです。。。)。
単位はmmまたはLに統一しています。
日本で手に入らなかったり現状手に入らなかったりするものも載せてるかもしれません。
選抜基準はフルサイズGPUが載ることと容量が12L未満であることです。

名前 W H D CPUクーラー高 GPU L GPU H カードスロット 容積 備考
Velka 5 109 303 174 48 296 142 2 5.7 縦置き
SFX電源推奨?
A4 SFX V4 112 200 317 48 295 144 2 7.2 積める中ではC7Gが一番冷えると思われる
SM550 139 208 335 55 300 133 2 9.7 GPU高はケーブルレイアウトによって157mmまで伸びる
ウィンドウ選択可
SM560 159 208 335 55 305 133 3 11
GHOST S1 MkII 140 188 322 66 305 ? 2 8.1 高さ132mm位のGPUは乗る
ウィンドウ選択可
GHOST S1 MkII Small Hat 140 204 322 66 305 ? 2 9.2 上に薄型ファンを積める
GHOST S1 MkII Medium Hat 140 214 322 66 305 ? 2 9.6 上に25mmファンを積める
GHOST S1 MkII Large Hat 140 245 322 66 305 ? 2 11.0 上に240mmラジェーターを積める
A50 140 210 330 66 300 134 2.5 9.7 アクリルサイドパネル
SG13 222 181 285 71 266 129 2 11.5 140mmラジェーターを積める
CPUクーラー高はSFX電源かつアダプダ前提で10mm盛った

感想

どれもCPUの冷却やばそう(小並感)。

CPUの水冷をやるつもりは無いのでクーラー選ぶのが結構きっついですね。 一応最低サイズでもCryorig C7Gが(発売されれば)積めるので、定格ならRyzen 9 3950X(TDP105W)も積めなくはないんですが、エアフローの悪さを考えればもう少し大きいクーラーを積みたい感も有ります。

個人的に驚きだったのが、Ncase M1の体積が12.6Lで載せられなかったことです。

参考にさせて頂いたサイト

【日記】読みやすいコードについて考えたこと

読みやすいコードとは何かについて個人的に思っていることについて書きます。
前提として、黒魔術的な話や自動整形で直せるような部分には触れません。

そもそも読みやすさとは何か?

最近のコードにおける読みやすさとは「その処理によって何がどう変化するか(しないか)を予測できること」だと自分は考えています。
今時の「動的型付け辛い」だとか「強力な型システムはいいぞ」だとか「関数型プログラミングはいいぞ」の流れも結局本質はそこにあると思っています。

要するに、文法の良し悪しだとか見た目がきれいだとかいう以上に何が起きるか(起きないか)を人間が予測しやすい形になっているかの方が問題だということです。

最近の言語はいかにして読みやすさを確保するか

最近のプログラミング言語は以下のような要素を実現することで読みやすさを確保していると思っています。

  • 強力な型システム
  • スコープを強力に区切ることによる外部への影響の限定
  • mutable / immutableの徹底

逆に言うと、これらに反するようなコードの書き方はあまりよろしくないものだと解釈しています。

具体的なコードの読みやすさ

「自分ならこう解釈する」という程度の話ですが、ここまでの流れを踏まえ、Javaでの一部機能を例にどちらが良いと感じるかを書きます。

if文 vs 三項演算子

三項演算子の方がよいと考えています。

理由は、if文ではその中で一体どのような副作用が発生するか分からないのに対し、三項演算子では恐らく代入しか行われていないことが想定しやすいからです。

一時変数を置く vs 置かない

極力置かないか、置いてもスコープが限定されていて使い捨てにされるべきだと考えています。

理由は、スコープ内に変数が増えれば増えるだけ何が起きるかの予測が難しくなるからです(e.g. 再代入されたり、リストの中身が別の場所で変更されるなど)。

StreamAPIやOptionalを上手く使えば一時変数と上手く付き合うことができますし、極力宣言される一時変数は少ない方が良いでしょう。

ただし、やりすぎると実際に読みにくくなるというのは確かだと思うので、「一時変数が無く読みやすい > 一時変数が適度に有る > 一時変数が無く読みにくい > 一時変数が多い」の順で良いコードだと考えています。

for文 vs forEach文

forEach文を使うべきだと考えています。

理由は、forEach文では外部の変数が変更されない(中身が変更できることはともかく!)ということが明示されるのに対し、for文や拡張for文では外部の変数に対して変更ができるため、動作の予測が難しくなるからです。

また、インデックスを使うようなfor文に関しても、これからはIntStream等のrangeを使うことで対応ができるので、これからは余程の事情が無ければ通常のfor文を用いるべきではないと思います。

読みやすさか能力不足か

このような話題を出した時、「とは言えこの書き方は読みにくいんじゃないか?」という意見が出ることは有りますし、実際自分も「この書き方だと読みにくいんじゃないか、読みにくいなら使わない方がいいんじゃないか」と感じたことも有ります。

ただ、エンジニアになって半年以上開発を続けた結果、これはコードが読みにくいのではなく自分の能力が不足しているということなのだと解釈するようになりました。

理由は以下の3点です。

  1. 鬼強い人らが集まって決めたプログラミング言語の仕様だから嬉しさは必ず有る
  2. その嬉しさを使わなければ損をする
  3. 嬉しさを使わない理由が能力不足なら悪いのは自分

確かに新しいものを積極的に使おうと思えば覚えることは非常に多岐に渡ります。
一方、何故新しいものが追加されたかと言えばそれに嬉しさが有るからです。

少なくとも当分技術で食って行こうと思うなら、プログラミング言語に新しく追加された機能からなるべく早い時期に嬉しさを引き出そうという姿勢は必要だと思います。

とは言え既存のコードの秩序を破壊するべきなのか?

エンジニアは日々成長する生物であるため、コードを書いていく中でより良い書き方に出会うことは多々あると思いますが、その時どのタイミングでどのようにより良いコードを取り込んでいくかという話です。
これには以下3つの選択肢が有ると思います。

  1. 全面的なコードの改修を含めた対応を行う
  2. 新しいコードは原則それを用い、既存は順次改修していく
  3. それを用いない

チームで相談して1を選べるなら特に問題は有りませんが、2の選択肢を選ぶ場合既存のコードと整合性が取れなくなることについてどうするべきかという話になるでしょう。
また、それを用いると見た目がガラッと変わるため、読みにくく感じてしまう場合も有ると思います。

それでも、自分は以下3点から2の選択肢を取るべきだと思います。

  • 読み書きしていけば文法には慣れる
  • 実装レベルでの文法ブレはそこまで重大な問題ではない
  • 直していった方が将来的なバグを防げる

まとめ

読みやすいコードとそれを書いていく上での心構え的な部分をまとめました。

かなり原理主義的な意見だという自覚は有りますが、個人的にはこのスタンスでやっていくことが結局コード品質の向上につながるだろうと思っています。