5 ms·
So, I have a question. I have a kind of serial number, and different systems expect slightly different formats. One system likes dashes, one doesn't, one system
by cjohnson318 6y ago
So, I have a question. I have a kind of serial number, and different systems expect slightly different formats. One system likes dashes, one doesn't, one system likes an extra two digits, while another system likes an extra four numbers. Should I write around n(n-1)/2 pure function converters between n systems? Or one class with n methods? (If you're curious, I'm talking about oil well API numbers. It's not rocket science, I'm just curious what y'all think.)
- Matheus28 6y agoIf you REALLY have to use all these different formats, I'd have one canonical one used everywhere in your app, and 2n methods to convert to different ones at api boundaries.
- cjohnson318 6y agoAh! Thank you, that is a very good middle road.
- brundolf 6y agoI'd have one canonical one used everywhere, and 2n pure functions to convert at API boundaries. By making them pure functions you guarantee (or at least suggest by convention; depending on your language's type system) that those conversions will have no side-effects. As methods, you can never be sure as the caller whether there will be ramifications to calling them in new places.
- bigbizisverywyz 6y agoAnother advantage of that approach is that if you make sure you always persist the serial number in the canonical format, and immediately parse the incoming value into the canonical form, then comparing 2 serial numbers is easy and consistent - including e.g. when constructing db queries. I encountered a similar problem where an identity number could be represented in different formats, and the solution had been to store the string representation in all its glorious permutations. Doing db queries to find anything by that key was then impossible until the representation had been made consistent. Then when e.g. creating reports for different systems we could format the output as per that systems expectation.
- trylist 6y agoThis sounds like a graph problem similar to the google unit conversion problem (https://alexgolec.dev/ratio-finder/ https://alexgolec.dev/ratio-finder/). You could probably do a data driven solution, but the gist is convert to and from one normalized form. Then it's n*2 functions. This is probably what you're implicitly doing with the class solution you're talking about.
- Geminidog 6y agoWhy n(n-1) pure functions? It makes no sense that you only need n methods in a class and suddenly n(n-1) pure functions. You will always need n(n-1) functions if you want to specify ALL the conversion logic. Think about it. If you're not writing it in the method, then that logic must be written down somewhere. I think I get where you're coming from though. The class hides a type representation that is used as the "internal" representation of the serial number so you only need to write 2n functions. N function to convert to the special serial types, and N functions/logic to convert the special serial types to the internal serial type. The latter N functions are placed in the constructor not as functions but as a series of procedures to deduce the type of the parameter and do the conversion internally. (The effect of this is identical to overloading the constructor). Let's say A represents that internal serial type, with all other letters in the alphabet representing the serial types of your oil well. You're essentially doing the same as writing: AtoB :: B -> A BtoA :: A -> B CtoA :: C -> A AtoC :: A -> C If the goal was to convert B to C with classes you do this: Serial(B).CtoA() with functions you do this: AtoC(BtoA(A)) Your BtoA logic is simply hidden in the constructor of Serial. But basically the exact amount of written logic is occurring here. I think your question was a trap. One class with n methods is obviously better then n(n-1)/2. I think you were just unable to see that it's basically all functions and expressions in the end. When you use classes you are simply tying these functions to structure and internal variables making them less modular, but the amount of logic is exactly the same. But overall, if you want to know which methodology is logically better and more resistant to technical debt then I will tell you. The functional approach is better. Because the functional approach modularized BtoA. BtoA can be reused in other contexts in the functional approach but in the Object Oriented approach the logic of BtoA is tied together with CtoA, DtoA, EtoA and all of that in the constructor. Likely if you needed that logic as a one off... say to print the serials in internal receipts... you would likely be copying and pasting that logic from the constructor and duplicating it in another class when you follow the object oriented approach. This is the main reason why the author of the post promotes pure functions. Greater modularity and greater resistance to technical debt.
- carapace 6y agoHow big is n and how often does it change?