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 endDate
diese 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 total
aus den Parametern numMonths
und 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 endDate
selbst 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.
Date
liefern 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 Date
einmal. Es ist nicht unmöglich, das Richtige zu tun - Moment handhabt es viel besser, aber es ist sehr ärgerlich, es trotzdem zu benutzen.
monthlyPayment
gegebenen Fall umgehen sollen, der jedoch total
kein 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.3
und aus monthlyPayment = 0.1
).