Wir haben eine API-Funktion, die einen Gesamtbetrag basierend auf den angegebenen Start- und Enddaten in monatliche Beträge aufteilt.
// JavaScript
function convertToMonths(timePeriod) {
// ... returns the given time period converted to months
}
function getPaymentBreakdown(total, startDate, endDate) {
const numMonths = convertToMonths(endDate - startDate);
return {
numMonths,
monthlyPayment: total / numMonths,
};
}
Kürzlich wollte ein Verbraucher für diese API den Datumsbereich auf andere Weise angeben: 1) durch Angabe der Anzahl der Monate anstelle des Enddatums oder 2) durch Angabe der monatlichen Zahlung und Berechnung des Enddatums. In Reaktion darauf hat das API-Team die Funktion folgendermaßen geändert:
// JavaScript
function addMonths(date, numMonths) {
// ... returns a new date numMonths after date
}
function getPaymentBreakdown(
total,
startDate,
endDate /* optional */,
numMonths /* optional */,
monthlyPayment /* optional */,
) {
let innerNumMonths;
if (monthlyPayment) {
innerNumMonths = total / monthlyPayment;
} else if (numMonths) {
innerNumMonths = numMonths;
} else {
innerNumMonths = convertToMonths(endDate - startDate);
}
return {
numMonths: innerNumMonths,
monthlyPayment: total / innerNumMonths,
endDate: addMonths(startDate, innerNumMonths),
};
}
Ich glaube, diese Änderung erschwert die API. Nun muss der Anrufer Sorge um die versteckte Heuristik mit der Umsetzung der Funktion bei der Bestimmung , welche Parameter nehmen Präferenz verwendet wird , um den Datumsbereich (dh nach der Reihenfolge ihrer Priorität zu berechnen monthlyPayment, numMonths, endDate). Wenn ein Aufrufer die Funktionssignatur nicht beachtet, sendet er möglicherweise mehrere der optionalen Parameter und ist verwirrt, warum endDatediese ignoriert werden. Dieses Verhalten legen wir in der Funktionsdokumentation fest.
Außerdem habe ich das Gefühl, dass dies einen schlechten Präzedenzfall darstellt und der API Verantwortlichkeiten hinzufügt, mit denen sie sich nicht befassen sollte (dh die SRP verletzen). Angenommen, zusätzliche Verbraucher möchten, dass die Funktion mehr Anwendungsfälle unterstützt, z. B. das Berechnen totalaus den Parametern numMonthsund monthlyPayment. Diese Funktion wird mit der Zeit immer komplizierter.
Ich bevorzuge es, die Funktion so zu belassen, wie sie war, und stattdessen den Anrufer aufzufordern, sich endDateselbst zu berechnen . Ich kann mich jedoch irren und habe mich gefragt, ob die vorgenommenen Änderungen eine akzeptable Möglichkeit zum Entwerfen einer API-Funktion darstellen.
Gibt es alternativ ein allgemeines Muster für den Umgang mit solchen Szenarien? Wir könnten zusätzliche Funktionen höherer Ordnung in unserer API bereitstellen, die die ursprüngliche Funktion umschließen, aber dies bläht die API auf. Möglicherweise könnten wir einen zusätzlichen Flag-Parameter hinzufügen, der angibt, welcher Ansatz innerhalb der Funktion verwendet werden soll.
Dateliefern können. Sie können eine Zeichenfolge angeben und sie kann analysiert werden, um das Datum zu bestimmen. Auf diese Weise können die Handhabungsparameter jedoch auch sehr schwierig sein und zu unzuverlässigen Ergebnissen führen. Sehen Sie noch Dateeinmal. Es ist nicht unmöglich, das Richtige zu tun - Moment handhabt es viel besser, aber es ist sehr ärgerlich, es trotzdem zu benutzen.
monthlyPaymentgegebenen Fall umgehen sollen, der jedoch totalkein ganzzahliges Vielfaches davon ist. Und auch, wie man mit möglichen Gleitkomma-Rundungsfehlern umgeht, wenn die Werte nicht garantiert ganze Zahlen sind (z. B. probieren Sie es mit total = 0.3und aus monthlyPayment = 0.1).