Is there a pattern for handling conflicting function parameters?How do you deal with errors in enumeration /...

How does Monks' Improved Unarmored Movement work out of combat?

Delete n lines skip 1 line script

Was the ruling that prorogation was unlawful only possible because of the creation of a separate supreme court?

How to study endgames?

Verb ending in -ん with positive meaning?

Is there an in-universe explanation of how Frodo's arrival in Valinor was recorded in the Red Book?

IEEE 754 square root with Newton-Raphson

A word that refers to saying something in an attempt to anger or embarrass someone into doing something that they don’t want to do?

Can adverbs modify adjectives?

does 'java' command compile the java program?

Is it good to engage in exceptional cases where it is permissible to do a typically forbidden action to which one has a taivah for

Why has Speaker Pelosi been so hesitant to impeach President Trump?

Can an energy drink or chocolate before an exam be useful ? What sort of other edible goods be helpful?

Beyond Futuristic Technology for an Alien Warship?

Is it possible to take a database offline when doing a backup using an SQL job?

Is there any site with telescopes data?

Phonetic distortion when words are borrowed among languages

Should I be an author on another PhD student's paper if I went to their meetings and gave advice?

French license plates

Incomplete iffalse: How to shift a scope in polar coordinate?

Avoiding dust scattering when you drill

Writing a program that will filter the integer solutions

Which Catholic priests were given diplomatic missions?

Garage door sticks on a bolt



Is there a pattern for handling conflicting function parameters?


How do you deal with errors in enumeration / list processing (lowish-level API)As an API-user, would you tolerate BestPractice Exceptions?When writing a library or an API, when should and when shouldn't I validate or automatically correct errors in data provided by another developer?Idiomatic wrapping of C++ template type API in CCollection properties and initializer lists in .Net API designWhat HTTP action and return value should be used on resource's actionHandling Different Parameters for Derived Classes






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







2















We have an API function that breaks down a total amount into monthly amounts based on given start and end dates.



// 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,
};
}


Recently, a consumer for this API wanted to specify the date range in other ways: 1) by providing the number of months instead of the end date, or 2) by providing the monthly payment and calculating the end date. In response to this, the API team changed the function to the following:



// 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),
};
}


I feel this change complicates the API. Now the caller needs to worry about the heuristics hidden with the function's implementation in determining which parameters take preference in being used to calculate the date range (i.e. by order of priority monthlyPayment, numMonths, endDate). If a caller doesn't pay attention to the function signature, they might send multiple of the optional parameters and get confused as to why endDate is being ignored. We do specify this behavior in the function documentation.



Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.



My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.



Alternatively, is there a common pattern for handling scenarios like this? We could provide additional higher-order functions in our API that wrap the original function, but this bloats the API. Maybe we could add an additional flag parameter specifying which approach to use inside of the function.










share|improve this question






















  • 1





    "Recently, a consumer for this API wanted to [provide] the number of months instead of the end date" - This is a frivolous request. They can transform the # of months into a proper end date in a line or two of code on their end.

    – Graham
    7 hours ago


















2















We have an API function that breaks down a total amount into monthly amounts based on given start and end dates.



// 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,
};
}


Recently, a consumer for this API wanted to specify the date range in other ways: 1) by providing the number of months instead of the end date, or 2) by providing the monthly payment and calculating the end date. In response to this, the API team changed the function to the following:



// 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),
};
}


I feel this change complicates the API. Now the caller needs to worry about the heuristics hidden with the function's implementation in determining which parameters take preference in being used to calculate the date range (i.e. by order of priority monthlyPayment, numMonths, endDate). If a caller doesn't pay attention to the function signature, they might send multiple of the optional parameters and get confused as to why endDate is being ignored. We do specify this behavior in the function documentation.



Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.



My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.



Alternatively, is there a common pattern for handling scenarios like this? We could provide additional higher-order functions in our API that wrap the original function, but this bloats the API. Maybe we could add an additional flag parameter specifying which approach to use inside of the function.










share|improve this question






















  • 1





    "Recently, a consumer for this API wanted to [provide] the number of months instead of the end date" - This is a frivolous request. They can transform the # of months into a proper end date in a line or two of code on their end.

    – Graham
    7 hours ago














2












2








2








We have an API function that breaks down a total amount into monthly amounts based on given start and end dates.



// 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,
};
}


Recently, a consumer for this API wanted to specify the date range in other ways: 1) by providing the number of months instead of the end date, or 2) by providing the monthly payment and calculating the end date. In response to this, the API team changed the function to the following:



// 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),
};
}


I feel this change complicates the API. Now the caller needs to worry about the heuristics hidden with the function's implementation in determining which parameters take preference in being used to calculate the date range (i.e. by order of priority monthlyPayment, numMonths, endDate). If a caller doesn't pay attention to the function signature, they might send multiple of the optional parameters and get confused as to why endDate is being ignored. We do specify this behavior in the function documentation.



Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.



My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.



Alternatively, is there a common pattern for handling scenarios like this? We could provide additional higher-order functions in our API that wrap the original function, but this bloats the API. Maybe we could add an additional flag parameter specifying which approach to use inside of the function.










share|improve this question
















We have an API function that breaks down a total amount into monthly amounts based on given start and end dates.



// 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,
};
}


Recently, a consumer for this API wanted to specify the date range in other ways: 1) by providing the number of months instead of the end date, or 2) by providing the monthly payment and calculating the end date. In response to this, the API team changed the function to the following:



// 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),
};
}


I feel this change complicates the API. Now the caller needs to worry about the heuristics hidden with the function's implementation in determining which parameters take preference in being used to calculate the date range (i.e. by order of priority monthlyPayment, numMonths, endDate). If a caller doesn't pay attention to the function signature, they might send multiple of the optional parameters and get confused as to why endDate is being ignored. We do specify this behavior in the function documentation.



Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.



My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.



Alternatively, is there a common pattern for handling scenarios like this? We could provide additional higher-order functions in our API that wrap the original function, but this bloats the API. Maybe we could add an additional flag parameter specifying which approach to use inside of the function.







api-design






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago







CalMlynarczyk

















asked 8 hours ago









CalMlynarczykCalMlynarczyk

1144 bronze badges




1144 bronze badges











  • 1





    "Recently, a consumer for this API wanted to [provide] the number of months instead of the end date" - This is a frivolous request. They can transform the # of months into a proper end date in a line or two of code on their end.

    – Graham
    7 hours ago














  • 1





    "Recently, a consumer for this API wanted to [provide] the number of months instead of the end date" - This is a frivolous request. They can transform the # of months into a proper end date in a line or two of code on their end.

    – Graham
    7 hours ago








1




1





"Recently, a consumer for this API wanted to [provide] the number of months instead of the end date" - This is a frivolous request. They can transform the # of months into a proper end date in a line or two of code on their end.

– Graham
7 hours ago





"Recently, a consumer for this API wanted to [provide] the number of months instead of the end date" - This is a frivolous request. They can transform the # of months into a proper end date in a line or two of code on their end.

– Graham
7 hours ago










3 Answers
3






active

oldest

votes


















5

















Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.




You're exactly correct.




My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.




This isn't ideal either, because the caller code will be polluted with unrelated boiler plate.




Alternatively, is there a common pattern for handling scenarios like this?




Introduce a new type, like DateInterval. Add whatever constructors make sense (start date + end date, start date + num months, whatever.). Adopt this as the common-currency types for expressing intervals of dates/times throughout your system.






share|improve this answer


























  • Are you aware that in a weakly typed language like JavaScript a constructor DateTime(startDate,endDate) cannot be distinguished from a constructor DateTime(startDate,numOfMonths)?

    – Doc Brown
    7 hours ago








  • 1





    @DocBrown Yep. In such cases (Ruby, Python, JS), it's customary to just use static/class methods. But that's an implementation detail, that I don't think is particularly relevant to my answer's point ("use a type").

    – Alexander
    6 hours ago



















4
















Seeing the implementation, it appears to me what you really require here is 3 different functions instead of one:



The original one:



function getPaymentBreakdown(total, startDate, endDate) 


The one providing the number of months instead of the end date:



function getPaymentBreakdownByNoOfMonths(total, startDate, noOfMonths) 


and the one providing the monthly payment and calculating the end date:



function getPaymentBreakdownByMonthlyPayment(total, startDate, monthlyPayment) 


Now, there are no optional parameters any more, and it should be pretty clear which function is called how and for which purpose. Note the different function names don't mean you have to repeat any logic - internally, if these 3 functions share some common logic, it should be refactored to a "private" function.




is there a common pattern for handling scenarios like this




I don't think there is a "pattern" (in the sense of the GoF design patterns) which describes good API design. Using self-describing names, functions with fewer parameters, functions with orthogonal (=independent) parameters, are just basic principles of creating readable, maintainable and evolvable code. Not every good idea in programming is necesarily a "design pattern".






share|improve this answer



































    0
















    Sometimes fluent-expressions help on this:



    let payment1 = forTotalAmount(1234)
    .breakIntoPayments()
    .byPeriod(months(2));

    let payment2 = forTotalAmount(1234)
    .breakIntoPayments()
    .byDateRange(saleStart, saleEnd);

    let monthsDue = forTotalAmount(1234)
    .calculatePeriod()
    .withPaymentsOf(12.34)
    .monthly();


    Given enough time to design, you can come up with a solid API that acts similar to a domain-specific-language.



    The other big advantage is that IDEs with autocomplete make almost irrevelant to read the API documentation, as is intuitive due its self-discoverable capabilities.






    share|improve this answer






























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "131"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });















      draft saved

      draft discarded
















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f398828%2fis-there-a-pattern-for-handling-conflicting-function-parameters%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      5

















      Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.




      You're exactly correct.




      My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.




      This isn't ideal either, because the caller code will be polluted with unrelated boiler plate.




      Alternatively, is there a common pattern for handling scenarios like this?




      Introduce a new type, like DateInterval. Add whatever constructors make sense (start date + end date, start date + num months, whatever.). Adopt this as the common-currency types for expressing intervals of dates/times throughout your system.






      share|improve this answer


























      • Are you aware that in a weakly typed language like JavaScript a constructor DateTime(startDate,endDate) cannot be distinguished from a constructor DateTime(startDate,numOfMonths)?

        – Doc Brown
        7 hours ago








      • 1





        @DocBrown Yep. In such cases (Ruby, Python, JS), it's customary to just use static/class methods. But that's an implementation detail, that I don't think is particularly relevant to my answer's point ("use a type").

        – Alexander
        6 hours ago
















      5

















      Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.




      You're exactly correct.




      My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.




      This isn't ideal either, because the caller code will be polluted with unrelated boiler plate.




      Alternatively, is there a common pattern for handling scenarios like this?




      Introduce a new type, like DateInterval. Add whatever constructors make sense (start date + end date, start date + num months, whatever.). Adopt this as the common-currency types for expressing intervals of dates/times throughout your system.






      share|improve this answer


























      • Are you aware that in a weakly typed language like JavaScript a constructor DateTime(startDate,endDate) cannot be distinguished from a constructor DateTime(startDate,numOfMonths)?

        – Doc Brown
        7 hours ago








      • 1





        @DocBrown Yep. In such cases (Ruby, Python, JS), it's customary to just use static/class methods. But that's an implementation detail, that I don't think is particularly relevant to my answer's point ("use a type").

        – Alexander
        6 hours ago














      5














      5










      5










      Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.




      You're exactly correct.




      My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.




      This isn't ideal either, because the caller code will be polluted with unrelated boiler plate.




      Alternatively, is there a common pattern for handling scenarios like this?




      Introduce a new type, like DateInterval. Add whatever constructors make sense (start date + end date, start date + num months, whatever.). Adopt this as the common-currency types for expressing intervals of dates/times throughout your system.






      share|improve this answer














      Additionally I feel it sets a bad precedent and adds responsibilities to the API that it should not concern itself with (i.e. violating SRP). Suppose additional consumers want the function to support more use cases, such as calculating total from the numMonths and monthlyPayment parameters. This function will become more and more complicated over time.




      You're exactly correct.




      My preference is to keep the function as it was and instead require the caller to calculate endDate themselves. However, I may be wrong and was wondering if the changes they made were an acceptable way to design an API function.




      This isn't ideal either, because the caller code will be polluted with unrelated boiler plate.




      Alternatively, is there a common pattern for handling scenarios like this?




      Introduce a new type, like DateInterval. Add whatever constructors make sense (start date + end date, start date + num months, whatever.). Adopt this as the common-currency types for expressing intervals of dates/times throughout your system.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered 8 hours ago









      AlexanderAlexander

      1,3278 silver badges16 bronze badges




      1,3278 silver badges16 bronze badges
















      • Are you aware that in a weakly typed language like JavaScript a constructor DateTime(startDate,endDate) cannot be distinguished from a constructor DateTime(startDate,numOfMonths)?

        – Doc Brown
        7 hours ago








      • 1





        @DocBrown Yep. In such cases (Ruby, Python, JS), it's customary to just use static/class methods. But that's an implementation detail, that I don't think is particularly relevant to my answer's point ("use a type").

        – Alexander
        6 hours ago



















      • Are you aware that in a weakly typed language like JavaScript a constructor DateTime(startDate,endDate) cannot be distinguished from a constructor DateTime(startDate,numOfMonths)?

        – Doc Brown
        7 hours ago








      • 1





        @DocBrown Yep. In such cases (Ruby, Python, JS), it's customary to just use static/class methods. But that's an implementation detail, that I don't think is particularly relevant to my answer's point ("use a type").

        – Alexander
        6 hours ago

















      Are you aware that in a weakly typed language like JavaScript a constructor DateTime(startDate,endDate) cannot be distinguished from a constructor DateTime(startDate,numOfMonths)?

      – Doc Brown
      7 hours ago







      Are you aware that in a weakly typed language like JavaScript a constructor DateTime(startDate,endDate) cannot be distinguished from a constructor DateTime(startDate,numOfMonths)?

      – Doc Brown
      7 hours ago






      1




      1





      @DocBrown Yep. In such cases (Ruby, Python, JS), it's customary to just use static/class methods. But that's an implementation detail, that I don't think is particularly relevant to my answer's point ("use a type").

      – Alexander
      6 hours ago





      @DocBrown Yep. In such cases (Ruby, Python, JS), it's customary to just use static/class methods. But that's an implementation detail, that I don't think is particularly relevant to my answer's point ("use a type").

      – Alexander
      6 hours ago













      4
















      Seeing the implementation, it appears to me what you really require here is 3 different functions instead of one:



      The original one:



      function getPaymentBreakdown(total, startDate, endDate) 


      The one providing the number of months instead of the end date:



      function getPaymentBreakdownByNoOfMonths(total, startDate, noOfMonths) 


      and the one providing the monthly payment and calculating the end date:



      function getPaymentBreakdownByMonthlyPayment(total, startDate, monthlyPayment) 


      Now, there are no optional parameters any more, and it should be pretty clear which function is called how and for which purpose. Note the different function names don't mean you have to repeat any logic - internally, if these 3 functions share some common logic, it should be refactored to a "private" function.




      is there a common pattern for handling scenarios like this




      I don't think there is a "pattern" (in the sense of the GoF design patterns) which describes good API design. Using self-describing names, functions with fewer parameters, functions with orthogonal (=independent) parameters, are just basic principles of creating readable, maintainable and evolvable code. Not every good idea in programming is necesarily a "design pattern".






      share|improve this answer
































        4
















        Seeing the implementation, it appears to me what you really require here is 3 different functions instead of one:



        The original one:



        function getPaymentBreakdown(total, startDate, endDate) 


        The one providing the number of months instead of the end date:



        function getPaymentBreakdownByNoOfMonths(total, startDate, noOfMonths) 


        and the one providing the monthly payment and calculating the end date:



        function getPaymentBreakdownByMonthlyPayment(total, startDate, monthlyPayment) 


        Now, there are no optional parameters any more, and it should be pretty clear which function is called how and for which purpose. Note the different function names don't mean you have to repeat any logic - internally, if these 3 functions share some common logic, it should be refactored to a "private" function.




        is there a common pattern for handling scenarios like this




        I don't think there is a "pattern" (in the sense of the GoF design patterns) which describes good API design. Using self-describing names, functions with fewer parameters, functions with orthogonal (=independent) parameters, are just basic principles of creating readable, maintainable and evolvable code. Not every good idea in programming is necesarily a "design pattern".






        share|improve this answer






























          4














          4










          4









          Seeing the implementation, it appears to me what you really require here is 3 different functions instead of one:



          The original one:



          function getPaymentBreakdown(total, startDate, endDate) 


          The one providing the number of months instead of the end date:



          function getPaymentBreakdownByNoOfMonths(total, startDate, noOfMonths) 


          and the one providing the monthly payment and calculating the end date:



          function getPaymentBreakdownByMonthlyPayment(total, startDate, monthlyPayment) 


          Now, there are no optional parameters any more, and it should be pretty clear which function is called how and for which purpose. Note the different function names don't mean you have to repeat any logic - internally, if these 3 functions share some common logic, it should be refactored to a "private" function.




          is there a common pattern for handling scenarios like this




          I don't think there is a "pattern" (in the sense of the GoF design patterns) which describes good API design. Using self-describing names, functions with fewer parameters, functions with orthogonal (=independent) parameters, are just basic principles of creating readable, maintainable and evolvable code. Not every good idea in programming is necesarily a "design pattern".






          share|improve this answer















          Seeing the implementation, it appears to me what you really require here is 3 different functions instead of one:



          The original one:



          function getPaymentBreakdown(total, startDate, endDate) 


          The one providing the number of months instead of the end date:



          function getPaymentBreakdownByNoOfMonths(total, startDate, noOfMonths) 


          and the one providing the monthly payment and calculating the end date:



          function getPaymentBreakdownByMonthlyPayment(total, startDate, monthlyPayment) 


          Now, there are no optional parameters any more, and it should be pretty clear which function is called how and for which purpose. Note the different function names don't mean you have to repeat any logic - internally, if these 3 functions share some common logic, it should be refactored to a "private" function.




          is there a common pattern for handling scenarios like this




          I don't think there is a "pattern" (in the sense of the GoF design patterns) which describes good API design. Using self-describing names, functions with fewer parameters, functions with orthogonal (=independent) parameters, are just basic principles of creating readable, maintainable and evolvable code. Not every good idea in programming is necesarily a "design pattern".







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 7 hours ago

























          answered 7 hours ago









          Doc BrownDoc Brown

          143k25 gold badges267 silver badges423 bronze badges




          143k25 gold badges267 silver badges423 bronze badges


























              0
















              Sometimes fluent-expressions help on this:



              let payment1 = forTotalAmount(1234)
              .breakIntoPayments()
              .byPeriod(months(2));

              let payment2 = forTotalAmount(1234)
              .breakIntoPayments()
              .byDateRange(saleStart, saleEnd);

              let monthsDue = forTotalAmount(1234)
              .calculatePeriod()
              .withPaymentsOf(12.34)
              .monthly();


              Given enough time to design, you can come up with a solid API that acts similar to a domain-specific-language.



              The other big advantage is that IDEs with autocomplete make almost irrevelant to read the API documentation, as is intuitive due its self-discoverable capabilities.






              share|improve this answer
































                0
















                Sometimes fluent-expressions help on this:



                let payment1 = forTotalAmount(1234)
                .breakIntoPayments()
                .byPeriod(months(2));

                let payment2 = forTotalAmount(1234)
                .breakIntoPayments()
                .byDateRange(saleStart, saleEnd);

                let monthsDue = forTotalAmount(1234)
                .calculatePeriod()
                .withPaymentsOf(12.34)
                .monthly();


                Given enough time to design, you can come up with a solid API that acts similar to a domain-specific-language.



                The other big advantage is that IDEs with autocomplete make almost irrevelant to read the API documentation, as is intuitive due its self-discoverable capabilities.






                share|improve this answer






























                  0














                  0










                  0









                  Sometimes fluent-expressions help on this:



                  let payment1 = forTotalAmount(1234)
                  .breakIntoPayments()
                  .byPeriod(months(2));

                  let payment2 = forTotalAmount(1234)
                  .breakIntoPayments()
                  .byDateRange(saleStart, saleEnd);

                  let monthsDue = forTotalAmount(1234)
                  .calculatePeriod()
                  .withPaymentsOf(12.34)
                  .monthly();


                  Given enough time to design, you can come up with a solid API that acts similar to a domain-specific-language.



                  The other big advantage is that IDEs with autocomplete make almost irrevelant to read the API documentation, as is intuitive due its self-discoverable capabilities.






                  share|improve this answer















                  Sometimes fluent-expressions help on this:



                  let payment1 = forTotalAmount(1234)
                  .breakIntoPayments()
                  .byPeriod(months(2));

                  let payment2 = forTotalAmount(1234)
                  .breakIntoPayments()
                  .byDateRange(saleStart, saleEnd);

                  let monthsDue = forTotalAmount(1234)
                  .calculatePeriod()
                  .withPaymentsOf(12.34)
                  .monthly();


                  Given enough time to design, you can come up with a solid API that acts similar to a domain-specific-language.



                  The other big advantage is that IDEs with autocomplete make almost irrevelant to read the API documentation, as is intuitive due its self-discoverable capabilities.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 57 mins ago

























                  answered 1 hour ago









                  DanielCuadraDanielCuadra

                  1914 bronze badges




                  1914 bronze badges


































                      draft saved

                      draft discarded



















































                      Thanks for contributing an answer to Software Engineering Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f398828%2fis-there-a-pattern-for-handling-conflicting-function-parameters%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Taj Mahal Inhaltsverzeichnis Aufbau | Geschichte | 350-Jahr-Feier | Heutige Bedeutung | Siehe auch |...

                      Baia Sprie Cuprins Etimologie | Istorie | Demografie | Politică și administrație | Arii naturale...

                      Nicolae Petrescu-Găină Cuprins Biografie | Opera | In memoriam | Varia | Controverse, incertitudini...