1

いくつかのデバッグの後、既存の製品コードで次のことがわかりました。

public class SomeTTS {
    private static TTSSpeechListener mSpeechListener;
    private static TTSBreakListener mBreakListener;
    // more static (!!!) listeners
    private String mPath;

    public TTS(String path, TTSSpeechListener speechListener)
            throws RuntimeException {
        // ...
        mSpeechListener = speechListener;
        mBreakListener = null;
        // more listeners set to null
        // ...
    }
    // called from NATIVE code that I cannot change
    private static void onReceiveSpeechData(byte[] samples) {
        mSpeechListener.onSpeechData(samples);
    }
    // ...
}

このクラスは、ネイティブ ライブラリ (Android、NDK、JNI) のラッパーです。ネイティブ ライブラリ ソースにアクセスできません。(もちろん、問題はわかります。 の 2 番目のインスタンスを作成した後SomeTTS、1 番目のインスタンスはもう機能しません。) 私は少しショックを受けています。男子生徒以外からこのようなバグが発生するとは思いません。おそらく彼らは児童労働を利用していたのでしょう。あるいは、誰かがデモ コードと製品コードの違いをマネージャーに説明できなかった可能性が高いです。

とにかく、私はそれを機能させる必要があります。いくつかの考えはありますが、現時点で提案できることは完璧にはほど遠いものです。それをリファクタリングする方法はありますか?

4

1 に答える 1

0

これが私がしたことです: 私はクラスを壊したままにして、賢明な API を提供するクラスにラップしました。

これは TTS であり、TTS が一度に 1 つの要求だけを発するようにするのが合理的であるため、現在の SomeTTS インスタンスへの静的ポインターを使用し、呼び出しを同期させました。クラスを修正することはできませんでしたSomeTTSが、そのメソッドの呼び出しが正しいことを確認できました。つまり、一部のメソッドを呼び出さなかったということです。

public class SomeTTS {
    private TTSSpeechListener mSpeechListener;
    // ... more listeners, NOT static ...

    private static volatile SomeTTS currentTTS;
    protected static Object currentTtsAccessLock = new Object();

    public static TTSSpeechListener currentSpeechListener() {
        synchronized (currentTtsAccessLock) {
            return currentTTS == null ? null : currentTTS.mSpeechListener;
        }
    }
    public static void setCurrentTTS(SomeTTS tts) {
        synchronized (currentTtsAccessLock) {
            currentTTS = tts;
        }
    }

    // called from NATIVE code that I cannot change
    private static void onReceiveSpeechData(byte[] samples) {
        TTSSpeechListener speechListener = currentSpeechListener();
        if (speechListener != null) {
            speechListener.onSpeechData(samples);
        } else  {
            // Just no better idea. But this should never happen.
            Log.e("SomeTTS","ERROR: speechListener == null  samples: "+samples.length);
        }
    }

    // ...
}

それがこのクラスのすべてです。そのメソッドに対して不正な呼び出しを行う可能性は依然としてあります。規律はMyTTSEngine代わりに使用することです。そのクラスMyTTSEngineは実用的な API を提供します。SomeTTSではない。

class MyTTSEngine {
    private SomeTTS mTTS;
    private Object upperLevelTtsLock = new Object();

    // ...

    public void say(String text) {
        // ...
        synchronized (upperLevelTtsLock) {
            TTS.setCurrentTTS(mTTS);
            try {
                mTTS.clearAbortState();
                mTTS.synthesizeFromString(text);
            } finally {
                TTS.setCurrentTTS(null);
            }
        }
        // ...
    }
}
于 2013-02-20T05:51:34.650 に答える