GithubHelp home page GithubHelp logo

Custom currencies about money HOT 11 CLOSED

brick avatar brick commented on August 11, 2024
Custom currencies

from money.

Comments (11)

jkuchar avatar jkuchar commented on August 11, 2024 1

allow a currency code string to be provided for ISO currencies only

Seems good to me. 👍 It prevents anybody to break 3rd party code. It is still very simple to extend (create new currency).

If someone wants to introduce to create money in his own currency from string, he can always introduce his own global factory, this way he can't break anything.

function money($amount, $currencyString) {
    // 1) look up currency and assign into $currency
    return Money::of($amount, $currency);
}

// usage of custom global factory
$moneyInMyCurrency = money(16, 'PRG');

from money.

BenMorel avatar BenMorel commented on August 11, 2024 1

Serialization (using serialize(), at least) is not an issue, as we will serialize everything: the Currency object and its properties, the amount with its scale etc. unserialize() will reconstruct an equivalent object.

As for parse(), it was designed as a convenient way to recover a Money from its string representation.

TBH I've only used it in unit tests so far.

It's not a big deal to drop it, or at least restrict it to ISO currencies for now.

from money.

BenMorel avatar BenMorel commented on August 11, 2024 1

Personally I store my currencies as 3-letter strings in the DB, so the convenience of accepting a string for ISO currencies is nice. We'll do this then, strings for ISO only, and force objects for non-ISO currencies.

Ad side question: they do, for example Bitcoin is divisible to 8 places; Ethereum has a scale of 18, apparently

Interesting, thanks!

from money.

BenMorel avatar BenMorel commented on August 11, 2024 1

This was several years ago and the culprit was Zend_Date (ZF1). I had a Doctrine type for this class, and realized after a while that initialization of this class was very heavy.

It's definitely cheaper to instantiate your enums inconditionally, because they do not require a lot of code to be run. Money would be only slightly more expensive, but still, parsing a BigDecimal, parsing a Currency, doing some consistency checks and all, for a type that might not be used for sure, is a waste of resources IMHO. Mapping Doctrine types to proxy classes generated specially for your objects is another solution. But we're digressing :)

from money.

BenMorel avatar BenMorel commented on August 11, 2024

I just realized that if we follow this route, we won't be able to use parse() with custom currencies, not sure if this is a problem. This won't be possible, for example:

Money::parse('BTC 1.234000');

or we have to accept an optional CurrencyProvider instance as a second parameter.

from money.

jkuchar avatar jkuchar commented on August 11, 2024

That sounds like a serious issue if someone use this for serialization. (I do not) Do we want to support that at all? Does not seems that useful to me and there is a serious complexity involved in getting this right. (e.g. providing factory with currency list, which can create and reconstruct monies)

from money.

jiripudil avatar jiripudil commented on August 11, 2024

FWIW, I guess I'd be fine even with Money::of('9.90', ISOCurrency::of('USD'));, at least it adds clarity. In the code I work with (mainly e-commerce), there are not many places where currencies are instantiated directly; usually they are fetched from the database and there is a single authority that resolves them, e.g. a Doctrine Type object. But that's just one use case and it'd surely be a step back in terms of convenience.

Restricting code resolution to ISO currencies sounds like a good way to go 👍

Ad side question: they do, for example Bitcoin is divisible to 8 places; Ethereum has a scale of 18, apparently

from money.

VasekPurchart avatar VasekPurchart commented on August 11, 2024

I tend to agree with @jiripudil here, I think Money::of('9.90', ISOCurrency::of('USD')); is fine, because most of the time it would be more likely Money::of('9.90', $country); and I think the sooner the actual string converts to the ISOCurrency instance, the better, because you have a type check closer to where the string is originating from. I think this is broader than the DBAL type, you should actually manipulate the string values as seldom as possible, usually just in "infrastructure" code as the types, or other types of serializers (when you need to send/get them in an API etc.). I have a lot of experience with these, because I have been using Enums based on same premise for a long time now.

As for the Money::parse('BTC 1.234000');, I think this is quite convenient, but personally I would also not cringe on it, but I think this should either be working for all currencies (even custom, if they are supported), or not be there at all.

from money.

BenMorel avatar BenMorel commented on August 11, 2024

Honestly I would miss Money::of('9.90', 'USD') if it wasn't there.

Your reasoning is correct and I do use DBAL types as well, but more sparsely since a few years ago, when I profiled a slow app and realized that the CPU time was mostly spent on hydrating properties that were only rarely used. Now I'm mostly using a "proxy" approach, where the property contains the raw value (amount = int, currencyCode = string), and the getter reconstructs the object only when requested.

As for the Money::parse('BTC 1.234000');, I think this is quite convenient, but personally I would also not cringe on it, but I think this should either be working for all currencies (even custom, if they are supported), or not be there at all.

I may remove parse() for the time being. Note that for of(), I do think it makes sense to provide support for currency code strings only for ISO currencies, as these are the only official currencies in use today. I personally don't mind that other currencies cannot be provided as strings.

from money.

VasekPurchart avatar VasekPurchart commented on August 11, 2024

when I profiled a slow app and realized that the CPU time was mostly spent on hydrating properties that were only rarely used

This is interesting, maybe have a look at consistence/consistence-doctrine#7? I was actually solving this last week and testing on a lot of data. This is using an PostLoadListener, because I need to have per field additional parameter (the resulting instance's class), so using only a DBAL type is unfortunately not possible. But when you look at the timings, it seems that the overhead in the implementation after optimization is nearly negligible (as seen from the last test where I "skipped" the execution).

But in any way as noted in the referenced issue, I think that in most cases, when this comes into focus as being a problem, a lot of time its the case that Doctrine is used in a way, that is not suited for.

Anyway the particular implementation does not matter from my point of view, because even if it was lazy-evaluated I would want it to be abstracted away from the other code, so that again everywhere only ISOcurrency is expected.

from money.

BenMorel avatar BenMorel commented on August 11, 2024

Summary: methods accepting Currency|string will only accept ISO currency codes from now on. Custom currencies will be provided as objects only.

from money.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.