Post merge review updates for CommandHandler updates (#33658)

* Several updates: comments and remove inline

* Restyle

* Move TryAddResponseData into the cpp instead of the header

* Add override, virtual was a copy and paste

* Name argument

* Argument renaming and comment update

* Move EncoderToTLV into DataModel as it looks like a more generic place, maybe we end up re-using it

* Restyle

* Update copyright year

* Renames based on review comments

* More renames of args

* Fix compile

* Slight comment update

* More comment update after self-review

* More comment update after self-review

* Some renaming

* Restyle

* One more rename: EncodableType

* EncodeTo should be const
diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp
index 6077e09..3096854 100644
--- a/src/app/CommandHandler.cpp
+++ b/src/app/CommandHandler.cpp
@@ -113,6 +113,26 @@
     return status;
 }
 
+CHIP_ERROR CommandHandler::TryAddResponseData(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
+                                              DataModel::EncodableToTLV & aEncodable)
+{
+    ConcreteCommandPath responseCommandPath = { aRequestCommandPath.mEndpointId, aRequestCommandPath.mClusterId,
+                                                aResponseCommandId };
+
+    InvokeResponseParameters prepareParams(aRequestCommandPath);
+    prepareParams.SetStartOrEndDataStruct(false);
+
+    {
+        ScopedChange<bool> internalCallToAddResponse(mInternalCallToAddResponseData, true);
+        ReturnErrorOnFailure(PrepareInvokeResponseCommand(responseCommandPath, prepareParams));
+    }
+
+    TLV::TLVWriter * writer = GetCommandDataIBTLVWriter();
+    VerifyOrReturnError(writer != nullptr, CHIP_ERROR_INCORRECT_STATE);
+    ReturnErrorOnFailure(aEncodable.EncodeTo(*writer, TLV::ContextTag(CommandDataIB::Tag::kFields)));
+    return FinishCommand(/* aEndDataStruct = */ false);
+}
+
 CHIP_ERROR CommandHandler::ValidateInvokeRequestMessageAndBuildRegistry(InvokeRequestMessage::Parser & invokeRequestMessage)
 {
     CHIP_ERROR err          = CHIP_NO_ERROR;
diff --git a/src/app/CommandHandler.h b/src/app/CommandHandler.h
index b06064c..ae41ec1 100644
--- a/src/app/CommandHandler.h
+++ b/src/app/CommandHandler.h
@@ -33,6 +33,7 @@
 #include <app/CommandHandlerExchangeInterface.h>
 #include <app/CommandPathRegistry.h>
 #include <app/ConcreteCommandPath.h>
+#include <app/data-model/EncodableToTLV.h>
 #include <app/data-model/Encode.h>
 #include <lib/core/CHIPCore.h>
 #include <lib/core/TLV.h>
@@ -56,32 +57,6 @@
 namespace chip {
 namespace app {
 
-/// Defines an abstract class of something that can be encoded
-/// into a TLV with a given data tag
-class EncoderToTLV
-{
-public:
-    virtual ~EncoderToTLV() = default;
-
-    virtual CHIP_ERROR Encode(TLV::TLVWriter &, TLV::Tag tag) = 0;
-};
-
-/// An `EncoderToTLV` the uses `DataModel::Encode` to encode things.
-///
-/// Generally useful to encode things like <ClusterName>::Commands::<CommandName>::Type
-/// structures.
-template <typename T>
-class DataModelEncoderToTLV : public EncoderToTLV
-{
-public:
-    DataModelEncoderToTLV(const T & value) : mValue(value) {}
-
-    virtual CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) { return DataModel::Encode(writer, tag, mValue); }
-
-private:
-    const T & mValue;
-};
-
 class CommandHandler
 {
 public:
@@ -267,7 +242,7 @@
      * Adds the given command status and returns any failures in adding statuses (e.g. out
      * of buffer space) to the caller
      */
-    CHIP_ERROR FallibleAddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus,
+    CHIP_ERROR FallibleAddStatus(const ConcreteCommandPath & aRequestCommandPath, const Protocols::InteractionModel::Status aStatus,
                                  const char * context = nullptr);
 
     /**
@@ -277,9 +252,9 @@
     void AddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus,
                    const char * context = nullptr);
 
-    CHIP_ERROR AddClusterSpecificSuccess(const ConcreteCommandPath & aCommandPath, ClusterStatus aClusterStatus);
+    CHIP_ERROR AddClusterSpecificSuccess(const ConcreteCommandPath & aRequestCommandPath, ClusterStatus aClusterStatus);
 
-    CHIP_ERROR AddClusterSpecificFailure(const ConcreteCommandPath & aCommandPath, ClusterStatus aClusterStatus);
+    CHIP_ERROR AddClusterSpecificFailure(const ConcreteCommandPath & aRequestCommandPath, ClusterStatus aClusterStatus);
 
     /**
      * This adds a new CommandDataIB element into InvokeResponses for the associated
@@ -350,37 +325,34 @@
      * @param [in] aRequestCommandPath the concrete path of the command we are
      *             responding to.
      * @param [in] aData the data for the response.
-     *
-     * NOTE: this is a convenience function for `AddResponseDataViaEncoder`
      */
     template <typename CommandData>
-    inline CHIP_ERROR AddResponseData(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
+    CHIP_ERROR AddResponseData(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
     {
-        DataModelEncoderToTLV<CommandData> encoder(aData);
-        return AddResponseDataViaEncoder(aRequestCommandPath, CommandData::GetCommandId(), encoder);
+        DataModel::EncodableType<CommandData> encoder(aData);
+        return AddResponseData(aRequestCommandPath, CommandData::GetCommandId(), encoder);
     }
 
     /**
-     * API for adding a data response.  The encoded is generally expected to encode
-     * a ClusterName::Commands::CommandName::Type struct, but any
-     * object should work.
+     * API for adding a data response.  The `aEncodable` is generally expected to encode
+     * a ClusterName::Commands::CommandName::Type struct, however any object should work.
      *
      * @param [in] aRequestCommandPath the concrete path of the command we are
      *             responding to.
-     * @param [in] commandId the command whose content is being encoded.
-     * @param [in] encoder - an encoder that places the command data structure for `commandId`
-     *             into a TLV Writer.
+     * @param [in] aResponseCommandId the command whose content is being encoded.
+     * @param [in] aEncodable - an encodable that places the command data structure
+     *             for `aResponseCommandId` into a TLV Writer.
      *
      * Most applications are likely to use `AddResponseData` as a more convenient
      * one-call that auto-sets command ID and creates the underlying encoders.
      */
-    CHIP_ERROR AddResponseDataViaEncoder(const ConcreteCommandPath & aRequestCommandPath, CommandId commandId,
-                                         EncoderToTLV & encoder)
+    CHIP_ERROR AddResponseData(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
+                               DataModel::EncodableToTLV & aEncodable)
     {
         // Return early when response should not be sent out.
         VerifyOrReturnValue(ResponsesAccepted(), CHIP_NO_ERROR);
         return TryAddingResponse(
-            [&]() -> CHIP_ERROR { return TryAddResponseDataViaEncoder(aRequestCommandPath, commandId, encoder); });
+            [&]() -> CHIP_ERROR { return TryAddResponseData(aRequestCommandPath, aResponseCommandId, aEncodable); });
     }
 
     /**
@@ -398,21 +370,22 @@
      * @param [in] aData the data for the response.
      */
     template <typename CommandData>
-    inline void AddResponse(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
+    void AddResponse(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
     {
-        DataModelEncoderToTLV<CommandData> encoder(aData);
-        return AddResponseViaEncoder(aRequestCommandPath, CommandData::GetCommandId(), encoder);
+        DataModel::EncodableType<CommandData> encodable(aData);
+        return AddResponse(aRequestCommandPath, CommandData::GetCommandId(), encodable);
     }
 
     /**
-     * API for adding a response with a given encoder of TLV data.
+     * API for adding a response with a given encodable of TLV data.
      *
-     * The encoder would generally encode a ClusterName::Commands::CommandName::Type with
+     * The encodable would generally encode a ClusterName::Commands::CommandName::Type with
      * the corresponding `GetCommandId` call.
      */
-    void AddResponseViaEncoder(const ConcreteCommandPath & aRequestCommandPath, CommandId commandId, EncoderToTLV & encoder)
+    void AddResponse(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
+                     DataModel::EncodableToTLV & aEncodable)
     {
-        if (AddResponseDataViaEncoder(aRequestCommandPath, commandId, encoder) != CHIP_NO_ERROR)
+        if (AddResponseData(aRequestCommandPath, aResponseCommandId, aEncodable) != CHIP_NO_ERROR)
         {
             AddStatus(aRequestCommandPath, Protocols::InteractionModel::Status::Failure);
         }
@@ -667,48 +640,16 @@
     CHIP_ERROR AddStatusInternal(const ConcreteCommandPath & aCommandPath, const StatusIB & aStatus);
 
     /**
-     * Non-templated function called before DataModel::Encode when attempting to add a response,
-     * which does all the work needed before encoding the actual type-dependent data into the buffer.
-     *
-     * **Important:** If this function fails, the TLV buffer may be left in an inconsistent state.
-     * Callers should create snapshots as necessary before invoking this function and implement
-     * rollback mechanisms if needed.
-     *
-     * **Usage:** This function is intended to be called exclusively by TryAddResponseData. It was
-     * factored out to optimize code size.
-     *
-     * @param aRequestCommandPath  The concrete path of the command being responded to.
-     * @param aResponseCommandPath The concrete path of the command response.
-     */
-    CHIP_ERROR TryAddResponseDataPreEncode(const ConcreteCommandPath & aRequestCommandPath,
-                                           const ConcreteCommandPath & aResponseCommandPath)
-    {
-        InvokeResponseParameters prepareParams(aRequestCommandPath);
-        prepareParams.SetStartOrEndDataStruct(false);
-
-        ScopedChange<bool> internalCallToAddResponse(mInternalCallToAddResponseData, true);
-        return PrepareInvokeResponseCommand(aResponseCommandPath, prepareParams);
-    }
-
-    /**
      * If this function fails, it may leave our TLV buffer in an inconsistent state.
      * Callers should snapshot as needed before calling this function, and roll back
      * as needed afterward.
      *
-     * @param [in] aRequestCommandPath the concrete path of the command we are
-     *             responding to.
-     * @param [in] aData the data for the response.
+     * @param [in] aRequestCommandPath the concrete path of the command we are responding to
+     * @param [in] aResponseCommandId the id of the command to encode
+     * @param [in] aEncodable the data to encode for the given aResponseCommandId
      */
-    CHIP_ERROR TryAddResponseDataViaEncoder(const ConcreteCommandPath & aRequestCommandPath, CommandId commandId,
-                                            EncoderToTLV & encoder)
-    {
-        ConcreteCommandPath responseCommandPath = { aRequestCommandPath.mEndpointId, aRequestCommandPath.mClusterId, commandId };
-        ReturnErrorOnFailure(TryAddResponseDataPreEncode(aRequestCommandPath, responseCommandPath));
-        TLV::TLVWriter * writer = GetCommandDataIBTLVWriter();
-        VerifyOrReturnError(writer != nullptr, CHIP_ERROR_INCORRECT_STATE);
-        ReturnErrorOnFailure(encoder.Encode(*writer, TLV::ContextTag(CommandDataIB::Tag::kFields)));
-        return FinishCommand(/* aEndDataStruct = */ false);
-    }
+    CHIP_ERROR TryAddResponseData(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
+                                  DataModel::EncodableToTLV & aEncodable);
 
     void SetExchangeInterface(CommandHandlerExchangeInterface * commandResponder);
 
diff --git a/src/app/data-model/BUILD.gn b/src/app/data-model/BUILD.gn
index 6f38c05..d61b30a 100644
--- a/src/app/data-model/BUILD.gn
+++ b/src/app/data-model/BUILD.gn
@@ -18,6 +18,7 @@
     "BasicTypes.h",
     "DecodableList.h",
     "Decode.h",
+    "EncodableToTLV.h",
     "Encode.h",
     "FabricScoped.h",
     "FabricScopedPreEncodedValue.cpp",
diff --git a/src/app/data-model/EncodableToTLV.h b/src/app/data-model/EncodableToTLV.h
new file mode 100644
index 0000000..d8b0391
--- /dev/null
+++ b/src/app/data-model/EncodableToTLV.h
@@ -0,0 +1,62 @@
+/*
+ *    Copyright (c) 2024 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <app/data-model/Encode.h>
+#include <lib/core/CHIPError.h>
+#include <lib/core/TLV.h>
+
+namespace chip {
+namespace app {
+namespace DataModel {
+
+/// Defines an abstract class of something that can be encoded
+/// into a TLV with a given data tag
+class EncodableToTLV
+{
+public:
+    virtual ~EncodableToTLV() = default;
+
+    virtual CHIP_ERROR EncodeTo(TLV::TLVWriter & writer, TLV::Tag tag) const = 0;
+};
+
+/// An `EncodableToTLV` that uses `DataModel::Encode` to encode things in one call.
+///
+/// Applicable to any type for which `chip::app::DataModel::Encode` works. In
+/// particular, types like <ClusterName>::Commands::<CommandName>::Type
+/// can be used as a type here.
+template <typename T>
+class EncodableType : public EncodableToTLV
+{
+public:
+    /// Encodes the given value via `DataModel::Encode` when the underlying
+    /// encode is called.
+    ///
+    /// LIFETIME NOTE: uses a reference to value, so value must live longer than
+    ///                this object.
+    EncodableType(const T & value) : mValue(value) {}
+
+    CHIP_ERROR EncodeTo(TLV::TLVWriter & writer, TLV::Tag tag) const override { return DataModel::Encode(writer, tag, mValue); }
+
+private:
+    const T & mValue;
+};
+
+} // namespace DataModel
+} // namespace app
+} // namespace chip