tag:blogger.com,1999:blog-7821856652257554779.post1051061467427480006..comments2025-09-20T09:27:07.510+02:00Comments on Andrzej on Software: account.transfer(..) - is it good OOP?Andrzej Krzywdahttp://www.blogger.com/profile/06399276063142826365noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-7821856652257554779.post-34023161133684168942012-05-31T05:33:33.890+02:002012-05-31T05:33:33.890+02:00This comment has been removed by the author.Unknownhttps://www.blogger.com/profile/14105605750521656944noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-43296938453961822262012-05-30T11:40:25.052+02:002012-05-30T11:40:25.052+02:00PaymentOrder p = new PaymentOrder(); p.setRemitter...PaymentOrder p = new PaymentOrder();<br />p.setRemitterAccount(...)<br />p.setBeneficiaryAccount(...);<br />p.setAmount(new MonetaryAmount(new BigDecimal(&quot;200.00&quot;), Currencies.USD));<br />paymentService.debit(p);<br /><br />It really comes down to what makes sense in your particular context/use caseResistancehttps://www.blogger.com/profile/11194577844778185707noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-14033910552788183662012-05-30T09:49:58.465+02:002012-05-30T09:49:58.465+02:00That would make the Bank object some type of God o...That would make the Bank object some type of God object. I wouldn&#39;t do it. <br />http://en.wikipedia.org/wiki/God_objectAnonymoushttps://www.blogger.com/profile/09525024258644532063noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-1947048244252078742012-05-29T22:22:48.185+02:002012-05-29T22:22:48.185+02:00Your design will need to grow from your actual use...Your design will need to grow from your actual use case. What you propose may be sufficient, but there may be much more involved in &quot;transfer 200 to an account.&quot;<br /><br />For example, some systems might require double-entry accounting. I&#39;ve use a <a href="http://homepages.tcp.co.uk/~m-wigley/gc_wp_ded.html" rel="nofollow">helpful article on double-entry accounting</a> to guide my design in the past, and I&#39;d recommend reading it to help inform this discussion.<br /><br />That model seems over-engineered for many scenarios. For my use cases, building out a batch &amp; journal system was unnecessary -- volumes are low, and those can be added later. Additionally, I removed the separation between &quot;account&quot; and &quot;user&quot; since our system only ever has a single account per user.<br /><br />One way to consider whether the design is &quot;good&quot; is to figure out what you can and can&#39;t change if you adopt that design. By adopting the &quot;posting&quot; &amp; &quot;asset_type&quot; pattern from this (I always rename them to &quot;transaction&quot; and &quot;transaction_type&quot;), your system could easily grow to provide more complicated accounting and reporting functionality. Simply doing &quot;account.transfer(...)&quot; <i>might</i> indicate that you&#39;re missing supporting infrastructure, the lack of which might bite you later.Brendanhttps://www.blogger.com/profile/10322013970477157026noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-9381494508429618092012-05-29T22:19:51.297+02:002012-05-29T22:19:51.297+02:00I&#39;d just think about that like real money hand...I&#39;d just think about that like real money handling.<br /><br />* You are in control of your own pocket.<br />* Only you know how much money there are.<br />* Only you can take out money from your pocket and give it to other people (otherwise it is stealing).<br />* If receiving party doesn&#39;t want to take money then who cares, money is yours after all!<br /><br />So<br />John.give_money(allowance, JohnJr)nagisahttp://kazlauskas.menoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-28576059798975764362012-05-29T22:16:50.592+02:002012-05-29T22:16:50.592+02:00Accounts should not know about other accounts. The...Accounts should not know about other accounts. They don&#39;t need to. If it helps your code to let them manage transfers, your code is broken. I think examples keep it &#39;simple&#39; to prevent the introduction of semaphores etc at beginner level. Try multithreading an app where account.add() works :-SAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-74862021641356358082012-05-29T20:45:45.082+02:002012-05-29T20:45:45.082+02:00Why not something like: Account.deposit(otherAcco...Why not something like:<br /><br />Account.deposit(otherAccount.withdraw(200));<br /><br />Though I agree, putting it in a transaction object which can manage any exceptions is probably a better choice.<br /><br />JohnAnonymoushttps://www.blogger.com/profile/10678767248105726354noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-78003509782732028542012-05-29T20:18:58.955+02:002012-05-29T20:18:58.955+02:00I agree with kikito and have the same idea. Bank i...I agree with kikito and have the same idea. Bank is better for manage account, transfers etc, Transfer should have responsibility for changing account price. <br /><br />Responsibility for account is probably information about owner and price state, not for managing this data, and for risk operation like transfer I think special class is obvious.michałhttps://www.blogger.com/profile/14570977503420187531noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-66874301201555349672012-05-29T17:45:52.558+02:002012-05-29T17:45:52.558+02:00In my mind a balance (pardon the pun) needs to be ...In my mind a balance (pardon the pun) needs to be found between modelling the real semantics of the problem domain and writing maintainable easy to understand code. <br /><br />I think a Bank type would be something of a god class and open to abuse? <br /><br />A Transfer type maybe more sensible especially if it is invoked as a result of a transfer screen / api? <br /><br />I would argue that context is very important and in a large system you will have more than one context and thus more than one Transfer type. <br /><br />Concepts such as Boundary Contexts [1] are probably overkill in most applications though helpful in large financial apps (certainly from my expereince where they swifty turn into big balls of mud and entropy is smacking you on the nose with technical debt every day)<br /><br />Ultimately...it depends :)Ed Blackburnhttps://www.blogger.com/profile/17045008823330793876noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-70626282474091554302012-05-29T16:23:47.598+02:002012-05-29T16:23:47.598+02:00Just thinking... Isn&#39;t the bank an object doin...Just thinking... Isn&#39;t the bank an object doing a transfer within his infrastructure instead of transfer &quot;doing&quot; itself?<br /><br />Transfer.new(src, target, amount)<br />Bank#execute(transfer)<br /><br />There is several possible ways to di that. One is more OOP-ish than the other. This classic account#transfer is just to scratch the sufrace of OOP for beginners. Sadly some developers see nothing wrong with that.Michalnoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-18945059894663878722012-05-29T13:55:50.269+02:002012-05-29T13:55:50.269+02:00If it was really banking software it would probabl...If it was really banking software it would probably look more like:<br /><br />transaction = Transaction.new<br />transaction.add(Operation.new(account1, amouont, TYPE_DEBIT)<br />transaction.add(Operation.new(account2, amount, TYPE_CREDIT)<br />transaction.process<br /><br />And this snippet would be all over the place :)Martinhttp://lottestyle.denoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-47666558835470305882012-05-29T13:05:54.304+02:002012-05-29T13:05:54.304+02:00Bartosz, exactly, it&#39;s very common in Rails/Ac...Bartosz, exactly, it&#39;s very common in Rails/ActiveRecord, however as I wrote, this example is very popular in many other places.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-65818956076899375822012-05-29T13:02:48.662+02:002012-05-29T13:02:48.662+02:00In OOP, an Account should know nothing about other...In OOP, an Account should know nothing about other accounts. <br /><br />It&#39;s very common antipattern to find in &quot;too fat&quot; ActiveRecord models, responsible for everything related to them.Bartosz Blimkehttps://www.blogger.com/profile/08810234693165301502noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-51593317625659818072012-05-29T12:58:43.974+02:002012-05-29T12:58:43.974+02:00Thanks Paul, wise words. I&#39;m just unable to f...Thanks Paul, wise words.<br /><br />I&#39;m just unable to find models where it feels good that the source account should know about the target account, even for just one second.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-69049582958630665752012-05-29T12:56:30.960+02:002012-05-29T12:56:30.960+02:00There is an infinite number of ways to represent t...There is an infinite number of ways to represent this. You could really start to pull out every single piece of functionality into differing abstractions and combine them in wonderful ways.<br /><br />This example is used this way because its how many people think about transfers between accounts, and pretty much everyone has a bank account and does transfers. So its a universal concept.<br /><br />Many banks actually create a transfer object, containing the amounts, the two accounts. They apply initially a reduction in the source account (but its more complex than that) and then execute the transfer separately via a transfers system to other banks if needed. But how any organisation decides to do that really depends on their model of the world and the way it works for them.Paul Keeblehttps://www.blogger.com/profile/01672124418792339749noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-48187078174601023102012-05-29T12:54:01.624+02:002012-05-29T12:54:01.624+02:00Yes, wrapping it in a transfer object is certainly...Yes, wrapping it in a transfer object is certainly a good idea. <br /><br />I don&#39;t think that it may be an overkill in smaller apps. It&#39;s always good to have a nice OOP design.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-48613648423706664992012-05-29T12:48:47.412+02:002012-05-29T12:48:47.412+02:00Well, you certainly could do this: Transfer.new(2...Well, you certainly could do this:<br /><br />Transfer.new(200, source_account, dest_account)<br /><br /><br />The adecuacy of this depends on whether it makes sense to have Transfers as individual objects in your system. I a banking system it would probably make a lot of sense, but in a video store app it would probably be overkill.kikitohttps://www.blogger.com/profile/18268036925187262614noreply@blogger.com