このブログの運用と何をどこにアウトプットするかについて

プログラミング系の内容をQiitaに書きはじめ、趣味向けのサブブログを立ち上げ、その割に何をどこに書くかの話をまとめていませんでした。
ということで、今更ですが、このブログの運用と何をどこにアウトプットするかについてまとめます。

サブブログに何を書くか

wrongwrong-pc-parts.hatenablog.com

サブブログの方には、プログラミング以外の趣味の話や、ガジェット等のレビューを書きます。

Qiitaに何を書くか

qiita.com

Qiitaには、ある程度ボリュームが有って、環境や個別の事情に依存しないような、プログラミング・開発関連の内容を書こうと思っています。
ただし、明確に区切っている訳ではないため、このブログとどちらにアウトプットするかは不定です。

このブログに何を書くか

wrongwrong163377.hatenablog.com

このブログには、ボリュームが無かったり、環境や個別の事情に依存するような内容を中心に書いていきます。
ただし、前述の通り、Qiitaとの使い分けは明確にしていません。

また、たまに日記・意見表明のような記事も書くかもしれません。

終わりに

2017年に始めてから雑多な内容を書き続けてきたこのブログですが、個人的には先ごとにテーマを絞れている今の形の方がいいのかなと思っています。
アウトプット先は分散しましたが、アウトプットそのものは続けていこうと思っているので、引き続きよろしくお願いします。

【Windows】特定フォルダへの書き込み(ファイル作成)を禁止する

やること

あるディレクトリへのファイル作成を禁止します。

注意点

自分はプログラムからの書き込みを禁止しようと考えてこれを実行しましたが、これをやるとプログラムが正常に動かなかったです。

やり方

操作したいフォルダを右クリック -> プロパティを開き、その中のセキュリティタブに移動します。
すると、画像のようにユーザー一覧とアクセス許可が表示されます(画像ではユーザー名を消しているので見え方が不自然になっています)。

f:id:wrongwrongwrongwrong163377:20220130020102j:plain

この画面から編集(E)...を選択すると以下のような画面が開きます。
ここで下側のアクセス許可チェックボックスから、書き込み拒否チェックボックスをチェック・適用するとファイル作成を禁止できます。

f:id:wrongwrongwrongwrong163377:20220130020740j:plain

この状態でファイルの新規作成を選択しても、画像のように何も作成できない状態になっています。

f:id:wrongwrongwrongwrong163377:20220130021149p:plain

【Java】Unable to make private static int java.time.OffsetDateTime.compareInstant(java.time.OffsetDateTime,java.time.OffsetDateTime)...への対処

TL;DR

  • Java 16AssertJassertThatを使ってOffsetDateTime同士を比較するとエラーになる場合がある
    • Mockkに関しては直接の原因じゃない?
  • 原因はJDK内部のカプセル化の強化
  • Java 11に変えるか、オプションを指定することで解決できる

本文

冒頭に書いたような状況が発生しました。
その時のスタックトレース(掲載可能な部分)は以下のようになりました。

Unable to make private static int java.time.OffsetDateTime.compareInstant(java.time.OffsetDateTime,java.time.OffsetDateTime) accessible: module java.base does not "opens java.time" to unnamed module @6515c7f6
java.lang.reflect.InaccessibleObjectException: Unable to make private static int java.time.OffsetDateTime.compareInstant(java.time.OffsetDateTime,java.time.OffsetDateTime) accessible: module java.base does not "opens java.time" to unnamed module @6515c7f6
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
    at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
    at io.mockk.proxy.jvm.advice.MethodCall.call(MethodCall.kt:13)
    at io.mockk.proxy.jvm.advice.SelfCallEliminatorCallable.call(SelfCallEliminatorCallable.kt:14)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper.handleOriginalCall(JvmMockFactoryHelper.kt:83)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper.access$handleOriginalCall(JvmMockFactoryHelper.kt:20)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1$invocation$$inlined$stdFunctions$lambda$1.invoke(JvmMockFactoryHelper.kt:28)
    at io.mockk.impl.stub.MockKStub$handleInvocation$originalPlusToString$1.invoke(MockKStub.kt:227)
    at io.mockk.impl.stub.SpyKStub.defaultAnswer(SpyKStub.kt:15)
    at io.mockk.impl.stub.MockKStub.answer(MockKStub.kt:42)
    at io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:16)
    at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
    at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:263)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:25)
    at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:20)
    at java.base/java.time.OffsetDateTime.compareInstant(OffsetDateTime.java:182)
    at org.assertj.core.internal.OffsetDateTimeByInstantComparator.compare(OffsetDateTimeByInstantComparator.java:36)
    at org.assertj.core.internal.OffsetDateTimeByInstantComparator.compare(OffsetDateTimeByInstantComparator.java:18)
    at org.assertj.core.internal.ComparatorBasedComparisonStrategy.areEqual(ComparatorBasedComparisonStrategy.java:147)
    at org.assertj.core.internal.Comparables.areEqual(Comparables.java:122)
    at org.assertj.core.internal.Comparables.assertEqual(Comparables.java:117)
    at org.assertj.core.api.AbstractOffsetDateTimeAssert.isEqualTo(AbstractOffsetDateTimeAssert.java:380)

対処方法としては、冒頭で書いた通り、実行するJavaJava 11に変えるかオプションを指定することがあります。
オプション指定に関しては、例えばgradleだと以下のようにできます。

tasks.test {
        jvmArgs("--add-opens", "java.base/java.time=ALL-UNNAMED")
}

参考にさせて頂いた内容

github.com

【SpringBoot】java.lang.NoSuchFieldError: Companionで処理が失敗する状況への対処【OkHttp】

TL;DR

  • 自分の場合、Dependency Management PluginによってOkHttpのバージョンが書き換わったことが原因だった
    • com.squareup.okhttp3:okhttp:4.xが期待される所でcom.squareup.okhttp3:okhttp:3.14.9が利用されていた
  • gradledependenciesに利用したいバージョンのOkHttpを追加することで問題が解決した

本文

以下、問題の詳細やその他の情報について書きます。

Dependency Management Plugin周りの話

Dependency Management Plugin周りの詳細な話は別記事としてQiitaに投稿しています。 qiita.com

なぜこの問題が起きるのか

com.squareup.okhttp3:okhttp:4.x3.xの間には互換性が有りません。
特にKotlinの利用の有無は大きな違いです。
直接的なエラーの原因は、Kotlinによって生成されるであろうフィールドにアクセスしようとして失敗していることです。

Spring側の更新がされていない理由

READMEで言及されている通り、com.squareup.okhttp3:okhttp:3.xは既に更新が終了している状態です。 github.com

にも関わらずSpring側のバージョン指定が更新されていない理由は以下の通りです(issue内のやり取りから要約)。

  • SpringFrameworkcom.squareup.okhttp3:okhttp:3.xに依存している
  • SpringFrameworkKotlinに限ったプロジェクトではないため、Kotlinにも依存するcom.squareup.okhttp3:okhttp:4.xに移行することはできない

github.com

【JUnit5】MethodSourceで空Streamをエラーにしたくない場合の対処

状況

JUnit5ParameterizedTestで、MethodSourceが空Streamを返した場合、以下のようなエラーになります。

Configuration error: You must configure at least one set of arguments for this @ParameterizedTest
org.junit.platform.commons.PreconditionViolationException: Configuration error: You must configure at least one set of arguments for this @ParameterizedTest

このエラーは、例えば「Abstract Classにテストを定義し、各実装でMethodSourceを実装する」ような形でテストを実装している場合問題になります。

対処法

この問題は、EnabledIf/DisabledIfアノテーションを用い、テストを実行しないパターンを設定することで回避できます。
例えば以下のようになります(サンプルコードはKotlinですがJavaでも殆ど同じになります)。

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
abstract class Foo {
    abstract fun provider(): Stream<Arguments>

    private fun providerReturnsEmpty(): Boolean = provider().count() == 0L

    @ParameterizedTest
    @MethodSource("successProvider")
    @DisabledIf(value = "providerReturnsEmpty", disabledReason = "providerが空を返すため")
    fun test(/* 引数略 */) { /* テスト実装略 */ }
}

補足

EnabledIf/DisabledIfはどれ位何ができるか

EnabledIf/DisabledIfの詳しい使い方については以下のドキュメントで紹介されています。

junit.org

また、当該のドキュメントには出てきませんが、Springと組み合わせている場合SpELという記法で書くこともできます。

www.baeldung.com

ただ、個人的には、サンプルで紹介したようにbooleanを返す引数無し関数を定義するやり方をおすすめします。
理由は以下の通りです。

  • 読み書きに知識が必要になって面倒
  • アノテーション内で複雑なことをやり始めると(特にJavaでは)読みにくくなる

ParameterizedTestの方にオプションは無いのか

ParameterizedTestの方で空Streamをエラーにしないオプションは無いのか」と思われるかもしれませんが、それは提供されていないようでした。
詳しくは下記のissueにてやり取りが有ります(このオプションが欲しい方は👍を残すなりお願いします、自分は残しました)。

github.com

1年のアウトプットを振り返る

毎年やっている振り返りですが、今年もやります。

wrongwrong163377.hatenablog.com

アウトプットまとめ

まず今年1年で行った主なアウトプットです。

外部OSSへのコントリビュート

昨年のOSS活動は自作ライブラリへのコントリビュートが主でしたが、今年は多くの外部OSSにコントリビュートしました。
数だけなら8リポジトリに対してです。

外部OSSへのコントリビュートを始めたのは2020年の12月末からで、自分の時間の使い方としては一番大きな変化だったと思います。

多くはドキュメントやビルドスクリプトの微修正ですが、FasterXML/jackson-module-kotlinsquare/moshiには実際に動くコードでコントリビュートしました。
特にFasterXML/jackson-module-kotlinについては多くの修正・改善・機能追加を行いました。

外部OSSへのコントリビュートに関しては、来年も継続して行っていきたいと思っています。

自作ライブラリについて

自作ライブラリについては、正直メンテのモチベが下がっている状態です。
色々な改善案は思いついているものの、GitHubスターや利用者の反応はあまり得られず、かと言って宣伝等する気にもなれないので放置してしまっています。

正直、現状では上手いことモチベーションが湧くような機会待ちという感が有ります……。

ブログ

今年は特にブログでのアウトプット量は減少しました。
これは、OSSへのコントリビュートを始めたことも有りますが、新しいことに取り組む機会が少なかったり、精神的にモチベーションが低下していたことが大きいかなと思います。

それでも60本は書けており、2017年からの年間ブログ数50本記録は継続できました。

12月からは新しい会社で働きはじめ、新しいことに取り組む機会はどんどん増えていくものと思われるので、来年はアウトプット量を増やすことができればと思います。

終わりに

今年のアウトプット量は減ってしまいましたが、有名(= 沢山使われている)OSSに方々で貢献できたことも有って、アウトプットの価値は過去最高に高い1年だったのかなと思います。
ドキュメント修正・コードの両方でコントリビュートは続けていきたいです。

私事の方でもいい感じにアウトプットを続けていければと思っています。

それではよいお年を。