Using a Switch/Case List Versus HigherOrderFunctions
Continued from CustomBusinessApplicationDefinition.
Use a CASE list instead, as described. You imply case lists are somehow fragile. They are not unless you are Michael J. Fox without his meds. I doubt there is a need to keep adding yet more functions because the managers have to understand what the algorithms are, and they are not going to want 30 different scheduling algorithms. The work world doesn't work that way. They'll settle a few they are comfortable with and almost rarely add a new one. (There may be parameter/setting variations, but this is not part of [affected by] your pattern.) Thus, your "mass new HOF factory" is likely a myth. You are exaggerating a certain change pattern. It's as unrealistic as your sort comparer HOF injecter. It's a nice "lab toy" example, but doesn't fit real world change patterns. If you claim 30 is realistic, then describe all 30 of them to prove it! Otherwise I call "hogwash". -t
CASE lists are fragile because they require modifying the algorithm code every time a new implementation of the algorithm is needed. Only one algorithm implementation may be needed per application, but there may be many applications that use the same algorithm. That could practically mean recompiling a DLL or library for each new application that uses the DLL or library. Is that reasonable? The same applies to the canonical C/C++ sort() implementation. Should we have to recompile the C standard library for each application that needs sort()? As for parameter/setting variations, that is covered in my example on HofPattern. See the part that starts, "Now what if we need to customise based on some dynamic data, i.e., we require a data-dependent series of customisations?
I doubt there is a realistic biz situation where a developer is adding a new algorithm once a month or more. Like I said, most of the algorithms, such as the employee shift scheduling, are usually vetted and selected and chosen by management or the customer in the design process and are relatively stable there after. I doubt more than two new algorithms will be requested in an entire decade, and probably it would average around 1.0. So adding a new "look-up" line (function call) to the CASE list twice a decade is a big deal? I sounds like a ridiculous complaint to me.
It's not about adding a new algorithm. It's about adding a new implementation, i.e., a new application, of an existing algorithm. If you only need employee scheduling once, my argument for HOFs is inapplicable. You won't even need a "CASE list". However...
What if you maintain one employee scheduling application so the secretaries can resource meeting rooms, and another so the researchers can book access to the fume hoods in the labs, and another for the warehouse team so they can arrange extra cover for oversize loads? What if you develop a reputation for employee scheduling and become a "profit centre" selling your employee scheduling to two of your company's clients? Now you've got five applications that use the same basic scheduling algorithm, four of them use different SQL DBMSs with different schemas and the fifth uses a NoSql database. Do you really want to embed case statements -- one case per application -- in the same algorithm? Do you really want to maintain linkage to every application in the algorithm's source code? Do you really want to risk breaking the algorithm for everyone when one application changes?
Or, would you rather inject one HOF per application into the algorithm, and possibly never again have to look into the scheduling algorithm's source code, whilst you maintain entirely independent applications that use the algorithm and trivially support the "parameter/setting variations" you mentioned?
For me, it was an easy decision -- this was inspired by a real situation -- the HOF approach won.
- What you describe has turned at least in part turned into "packaged software", and is no longer "custom" (the "C" in CBA). It sounds like a hybrid of packaged and custom. Further, why can't one split the different algorithms up into different applications or sub-applications that use a shared library for the stuff common to all? Maybe this is hard in C/C++, but not with dynamic languages. I don't have a lot of production experience in C/C++ and so don't know what goofy limits it imposes on module-lizing. Unlike some of the other HOF examples, we don't have to "re-execute" the same function over and over again in a tight loop in this case. In most biz stuff, the database is doing the "heavy looping" (or equivalent) and not app code. If the app code is doing the heavy looping, its usually a design smell. That's another reason why the "sort-style" pattern doesn't appear often in biz apps. -t
- "Further, why can't one split the different algorithms up into different applications or sub-applications that use a shared library for the stuff common to all?" That's exactly what using a generic algorithm that accepts a function to customise it (i.e., HofPattern) enables. With HofPattern, you can factor your widely-used algorithms into a shared library and have all your applications make use of them, tailored to the specific application using a passed-in function; that library might never need to be changed once implemented, even as the applications using it chop and change. Without HofPattern, you have to put case statements inside your algorithm, and any change to the code using that algorithm might require changes to the algorithm too, therefore requiring changes to that shared library. -DavidMcLean?
- I'm talking about a separate application, not a case statement here. In your example, the secretaries (still such thing?) would have one app, and the researchers would have a different one. You would share libraries between each app for the stuff in common.
- Okay, so no case statement. That means the only way to customise an indivisible algorithm is by implementing it again for each application. Do you really think that's better than defining the algorithm once in a common library and having it accept customisation through a passed-in function? -DavidMcLean?
- I clarified the statement above.
- The original example wasn't mine. Regardless, your clarification does support the use of libraries for common functionality between apps. So how does you propose to handle the case of an indivisible algorithm needing customisation, as the original example presents, if not by having it accept a function argument? -DavidMcLean?
- Maybe it's only "indivisible" if one cannot think of a way to divide it at the time. I was hoping for a CBA UseCase/scenario to explore, but those appear to be quantumly entangled to HOF's such that both cannot appear on this wiki at the same time.
- I think it's safe to assume that your correspondents are competent and capable of recognising when an algorithm is divisible or not. Keep in mind that by "indivisible", we don't mean it absolutely can't be divided, only that by doing so we seriously compromise performance, simplicity, ease of use, and reliability of the algorithm's implementations.
- Demonstrate with a coded little sample that it's broken or fragile or what-not. Maybe I'll spot a DB-centric or Eval way to do it that he didn't think of, or something.
- It appears this wiki has already been down that route with GraphAlgorithmsWithTables. Assume DijkstrasAlgorithm is used, say, to implement logistics routing. Please show a DB-centric or "Eval way" to implement it.
- As for scenarios, HofPattern identifies the general pattern which applies to algorithms used in employee scheduling, automated room booking, costing, forecasting, logistics routing, and probably innumerable other algorithms applicable to business. I'm not convinced that being any more specific about these -- e.g., "Myrna manages a crew of nurses who are sent to clients' homes to provide in-home care. She needs to schedule her nurses so that blah blah blah..." -- would add anything but verbiage, since the technical considerations we're discussing here are independent of those specific requirements. If we're talking about employee scheduling, who cares who or what we're scheduling? It's ultimately a resource allocation problem. The algorithms we're talking about are often based on fundamental ComputerScience algorithms, like DijkstrasAlgorithm, AstarSearch, Monte Carlo methods, GeneticAlgorithms, and so on. These remain essentially the same regardless of requirements, and all are indivisible in that dividing them into blocks in order to avoid HOFs would compromise performance, simplicity, ease-of-use, and reliability of the implementation. I for one would rather pass a HOF into a monolithic implementation of an A* algorithm, than have to allocate an instance of A* and deftly weave its data structures into my application and carefully call its exposed methods in some prescribed sequence.
- With regard to employee scheduling, the original example, again again again I'm skeptical there will be boat-loads of INDEPENDENT algorithms actually used. It's likely managment would pick a half-dozen or so (at the most) and the frequency of additions will be relatively rare. Adding one new one every two years or so is not going to tax a CASE list. You probably have to change the drop-list to select the algorithm also, which requires a recompilation of the main or setup menu if using one of your stiff static compiling languages. Even if the drop-down list could "detect" the new HOF, it won't know the description of it. It would be better to sub-class if you need things like algorithm descriptions to be recognized. Then you could could have a "Title" element and the algorithm element/method. Or perhaps a ControlTable with Title and Algorithm (for "Eval") column. In dynamic languages there could be zero recompiling. In ExBase, for example, each subroutine could be a separate file, with a ".prg" extension. If adding an "Astar Search" algirithm, I just create "astar.prg", and enter it's title and the file name into a new row of the ControlTable. It then shows up on the menu (drop-down list) and works without recompiling. Walam!
// Example: Bertha-63
Set Processing Setup Screen
---------------------------------------
Employee set: Foo7 [*Select or create a different set*]
Please select scheduling algorithm to use for this set
[Astar-Search |v] // pulldown list
- Further, again in the stuff I work on, one starts using combos of parts of existing "algorithms" rather than new independent algorithms to gain flexibility, which lead to the discussion below. And 3rd, you haven't shown why it couldn't be split up into different applications with a shared libary. You haven't shown a down-side of this. You only claim, you don't SHOW. If there are many many different and useful scheduling algorithms, List them and describe them as evidence it's a likely situation. I've asked for this already. I'm skeptical there's going to a realistic situation where you are just popping in new independent algorithms all the time willy-nilly.
- Again, as has been pointed out repeatedly, despite your insistence that "again again again I'm skeptical there will be boat-loads of INDEPENDENT algorithms actually used", no one is suggesting that "there will be boat-loads of INDEPENDENT algorithms actually used". It's one algorithm used in multiple applications, with application-specific customisations for each application. Like, this application uses a SQL DBMS but that application uses NoSQL. And so on. Please re-read the scenario above; it's based on actual events.
- I'm not understanding the arrangement then. That's why UseCase(s) and UI mockups are important, despite your dismissal above as "verbiage". Plus, you had to complicate the situation because I "solved" the original. You keep cranking up the constraints. "If you are on a submarine and have to use C++ and only have 30 megs of hard-drive space and a torpedo is heading toward you..."
- Sorry, I don't know what you mean by "'solved' the original", and the constraints have remained constant from the beginning of HofPattern. By the way, HofPattern shows "the arrangement" via Javascript-like pseudo-code. If you do not understand the code, please ask and I'll be happy to explain how it works.
- The issue is being better, not merely working. And you left out important details, like the algorithm title (above). It almost appears you are copying our textbooks verbatim without first understanding the domain requirements.
- Again, if you do not understand the code, please ask and I'll be happy to explain how it works and how it's better than Eval, CASE statements, etc. Again. I don't know what you mean by "algorithm title", nor do I understand what you mean by "copying our textbooks verbatim." What textbooks?
- I understand the code. I never claimed it didn't work, although that's hard to know for sure without the biz requirement documents. What I don't understand is why it's allegedly "better" than the alternatives, such as for code maintenance. Further, it's unrealistic because it's not using the database for more of its processing. It will likely be more scalable also. You are violating GreencoddsTenthRuleOfProgramming by RAM-looping, etc. If you are not smart enough to de-RAM your tight loops, that's not my problem and not my blame. Rather than fussing with HOF's to avoid repeating loop structures, why not try to use more of the database instead? You could then pass around more SQL clauses/sub-strings and less HOF's. And store these strings or combo-controllers in the database so that a power user can save and manage the combo's via a more friendly screen instead of writing HOF's. A downside of HOF's is that you can't store them in a database. If you want flexibility to mix and match, then use strings. HOF's are outmoded 80's technology where everybody assumed that RAM-centric green-codding was a good thing. ComputerScience needs to update it's "standard algorithms" to fit modern RDBMS so that we don't have to do things the crappy 80's way with spaghetti function pointers, FP's GOTO. (That's what I mean by "textbooks verbatim".) Work on THAT instead of evangelizing Neanderthal HOF's.
- I think we've repeatedly covered why HOFs are superior to CASE statements, Eval and the like, and much of the "use more of the database instead" territory has been well-trodden before (see See GraphAlgorithmsWithTables, for example) but let's assume DijkstrasAlgorithm will be used to implement logistics routing. Given any scenario or requirements you like (within the context of using DijkstrasAlgorithm for routing, of course), please show how you would implement it to avoid HOFs and RAM-looping, whilst facilitating re-use of the DijkstrasAlgorithm implementation in multiple applications. By the way, the doubly-nested loops used in the HofPattern example were merely to illustrate an arbitrary indivisible algorithm. There wouldn't necessarily always be nested loops, or even loops at all. How a given algorithm would actually be implemented is, of course, down to the specific algorithm. It could even use a DBMS extensively without diminishing the benefit of HOFs, as per HofPattern.
- That's right, the devil's in the details, and you won't give any.
- Actually, no it isn't. Here's some details: The employee scheduling scenario schedules nurses to do home visits. Does that change anything? How about if we're scheduling teachers to deliver classes? Change anything now? Here's a hint: It changes nothing. I developed software for both, and the underlying algorithm is the same. The only thing that differs is how the algorithm is tied to specific database schemas primarily so fitness can be computed, and this is trivially injected as a HOF.
- It's already an industry heavily covered by packaged software: http://employee-scheduling-software-review.toptenreviews.com/
- Basically every common business application is already heavily covered by packaged software. Usually custom business software is requested not because it's a totally new field with no pre-existing packages available, but because a custom solution can be better tailored to the needs of the specific business; packaged business apps need all the features to satisfy their huge user bases, while custom biz apps can leave out any feature the specific business doesn't need, for example. The fact that there's plenty of packaged scheduling apps doesn't mean writing a custom scheduling app is suddenly invalid. -DavidMcLean?
- What missing features brought you into the picture?
- Top, is your rudeness necessary?
- Was that a rude question? I'm just trying to learn more about this scheduling domain so I can analyze its apps better.
- You mean, "what missing features brought you into the picture?" was a serious question about scheduling?
- Yes! Understanding the business reason why you are brought in to a project is generally a very good thing to know. For one thing, it tells you that the missing feature is very important to the organization, otherwise they'd use the off-the-shelf products. Orgs don't always tell you the priority or importance of features of a product or project such that one has to use all the cues they can. (Often times the requester doesn't explicitly know themselves, but their other actions reveal subconscious priorities.) If you know a given feature is very important, then you should spend extra time to get it right, including the design specs (ask good questions), the documentation, user interface, and perhaps performance tuning of it. --top
- Interesting. Your wording suggested a snide remark about the sudden appearance of a different correspondent in this thread. I didn't realise it was a serious question, because your correspondent was speaking in general and your response was quite specific. He referred to custom business apps removing features in general, so it seemed odd (to me, at least) for you to ask about specific missing features.
- I wish all participants would use a handle of some type to make sure I don't mistake Tom for Harry. Use a number if you don't want a name, as long as it's unique inside the topic page. -t
- I'm surprised you find us difficult to distinguish, or even that it would matter. When it matters (and it rarely does) I have no difficulty distinguishing you from others, via context, writing style, choice of words, and your IP address and/or domain name.
- That's because I cuss a lot at you miserable bastards :-) Anyhow, identifying the author is a good writing practice in general. Using writing style to determine is fraught with holes and risks. Note that I generally use the same italics/non-italics mode to indicate it's my reply etc. But if two+ people are using the same mode/markers, then the problems start. Some use curly braces to create a 3rd style, which is fine by me.
- It's still important to know why the above 13 products were rejected by the customer, otherwise employee scheduling may not be CBA, or at least rare CBA because such products are good enough the vast majority of the time such that custom-built scheduling software is a rare request. In all my years in the biz, I've never seen it done custom, and the high quantity of products in the field suggests why this is the case. -t
- In the context of this discussion, the reasons are utterly irrelevant. However, to quell your curiosity, I'll give you the reason: The project started before any of the commercial products existed.
- No, it's NOT irrelevant. Rolling your desktop operating system may have made sense in 1978, but it isn't 1978 anymore such that saying it's useful to focus on how to build desktop operating systems is now outdated, unless it's your specialty. (Unfortunately, our web GUI's are still stuck in the caveman days.)
- If the discussion is about programming techniques -- such whether to use case statements or HOFs (a bizarre dichotomy, but whatever) -- whether or not the whole application should be built is irrelevant. If it were even remotely relevant, then (for example) a discussion about using screws vs nails when putting up bathroom shelves should always be prefaced with a debate about whether or not some house on a particular street in a given city should be built, just because it happens to have a bathroom. As for "rolling yourown desktop operating system", isn't that a bit of an exaggeration? By "scheduling" I meant "employee scheduling", not "CPU task scheduling."
- But there is a pattern of apps, or parts of apps, that tend to be commoditized eventually, and I suspect employee scheduling falls under that. Certain techniques, such as HOFs, may have more benefit in such a pattern or environment. I admit I cannot be certain about this, not knowing much about employee scheduling techniques, but it's something that should be ruled out by picking something that doesn't appear to be commoditized. In other words, the pattern(s) in apps/tools that get commoditized may differ from those that don't such that demonstrating techniques for the first group may not be representative of the second group.
- Anything that can be packaged -- i.e., bundled up as a generic solution -- and is likely to benefit a profitable number of customers, will be commercialised. Inevitably, this will tend to be algorithms -- they have inherent value, because they represent a generic solution to a category of problems. An implementation of an algorithm can be sold to a number of customers, perhaps for varying purposes. The difference in pattern that you've observed is perhaps that the business code you work on tends to be highly-specific data-input, validation, and reporting. It is unlikely to benefit a commercially-profitable number of customers, and difficult to package in any generic way. That's because it's not algorithmic. It may be intricate and complex, but it isn't a process for solving a general category of problems; a typical application is probably a one-off process for meeting a highly-specific data-routing and/or presentation requirement.
- You are right, CBA's do tend to be specific. That's largely the nature of the niche. If a particular processing step is generic enough, it becomes packaged as an add-on or plug-in or what-not. Note that a TOP-oriented interface is one approach: describe the input tables and the output tables or columns. This way the solution doesn't have to be app-language-specific; it only has to speak SQL and then can hook into data on any SQL RDBMS. Graph optimization (shortest path, etc.) may do fairly well under such a setup, as long as an SQL expression or view can be supplied as the weighting expression(s). (It may require some pre-processing on the app side to prepare such.)
- It is precisely the "processing step [that] is generic enough" for which injecting customisations into or integrating the "add-on or plug-in" may benefit from HOFs. The specific use of "[i]nput tables and output tables or columns", which are inevitably schema-specific, can be made even more generic by injecting HOFs, which then allows the customisation to work with SQL tables, arbitrary data structures, or whatever the specific use of the add-on or plug-in might dictate. In short, HOFs are a more generic and flexible way of handling integration and/or customisation than SQL tables.
- No, because HOF's are app-language-specific. If the graph processing tool, for example, uses SQL as its interface, then there does not have to be a dedicated version or driver for each app language: C, VB, C#, Python, Ruby, Java, Fortran, COBOL, etc. which means the vendor can charge less because development doesn't have to be repeated per app language. Technically you may be correct, but not practically.
- It's trivial to provide a predefined HOF (or FunctorObject, in the case of languages that do not support HOFs) that defines a SQL interface. Thus, both forms of flexibility are simultaneously possible.
- Making a HOF is not the hard part, the hard part is "connecting" two different app systems/components. Further, the vast majority of the time, the data for a non-trivial CBA will be in an RDBMS anyhow. Only clueless newbies "keep" everything in arrays. Thus, there's little practical use in trying to cater to RAM-centric data structures, unless proven to be a trivial addition.
- Your response does not alter the truth of my statement.
- Anyhow, without a specific sample app to analyze, we'll probably go around in circles again.
- Probably. *sigh*
- I suspect the pattern is complex algorithms that have relatively few interconnections to other aspects of the app or organization. In other words, high processing but low interaction, relatively speaking. In such an environment, HOF's may shine in terms of making parts of the algorithm swappable with alternative implementations in "clean" chunks because there's less pesky interactions with "outside" issues.
- Any given fragmented algorithm can be altered to make it non-fragmented, and interconnections can be made generic and replaceable via DependencyInversion. HOFs facilitate this, as shown in HofPattern.
- And DependencyInversion has its downsides or limitations, as described in that topic.
- You mean the blurb under "Controversies"? That sounds like a negligible concern.
- Without examining a specific specimen, it's hard to tell either way. The ChangePattern(s) used for evaluation make a big difference.
- Actually, no. They make no difference. DependencyInversion shouldn't be something you refactor to achieve, it's what you do right from the beginning. It's a style of programming.
- Bull! ChangePatterns matter.
- By the way, how do you "de-RAM your tight loops"???
- Use the database instead of in-app loops. As far as converting DijkstrasAlgorithm to use mostly the database, I don't currently know how to do that. But the vast majority of algorithms I do use for CBA's I figure it out (pay me, and I dig into DA also). I have four weapons to use instead of HOFs: Database, Eval, CASE/conditionals, and OOP sub-classing. It's very rare when these are not sufficient either by themselves or in combo. You are tying to stretch things to force a case where none of those four work well. I'm wise to your trick. 99% of the time reality is more varied than you imply such that the chance of all four falling down for a given app or domain is almost zero. [I removed my cussing.]
- How, exactly, do you use the database instead of "in-app loops"? I'm not even sure what that means. We've already discussed, somewhat repetitively, how Eval and CASE/conditionals are inferior to HOFs in every respect. Not sure how "Database" got in there -- that's entirely orthogonal to HOFs (or anything else here.) As for OOP, yes you can certainly use sub-classing of algorithms or inject objects. Both of these wind up being functionally equivalent to HOFs, but require greater syntactic overhead than HOFs.
- "Greater syntactic overhead"? Minor at best, but they also have benefits, such as being able to dynamically control by settings and option switches stored in the database instead of having to hard-wire it into code so that power users can manage the variations and combos instead of programmers; and also allowing us to say add a title to the algorithm or function, per above. And your complaints about CASE is very weak unless you can justify frequent additions.
- No idea what adding "a title to the algorithm or function" is supposed to accomplish, you've been shown how HOFs can be loaded from databases, and I'd hardly call it a "weak" argument that provides a simple alternative to being forced to bind a generic algorithm to every application that uses it and have to edit and re-compile it whenever a new application uses it, when otherwise you might never have to edit it again. I'm still curious, by the way, how exactly you use the database instead of "in-app loops".
- Regarding the title, the app is going to have an algorithm selector similar to screen sample Bertha-63, correct?
- No. Once more, it's not one application with multiple implementations of an algorithm. It's one implementation of an algorithm used by multiple applications.
- Regarding loading HOF's into databases, you had to install a half-ass database written in the target language. We don't want to install and maintain a second database to save 3 keystrokes once every two years in a CASE statement. That's stupid.
- And there is almost no such thing as a "generic algorithm" in CBA's, at least not that we can know in advance. And if you have compiling difficulties, then use a dynamic language. I'm not going to write fucky code to cater to the damned compiler's whims. I'm not going to be a slave to outdated, anal, verbose technology. FORTRAN is dead, Jim (for CBA's).
- How do you know there's no such thing as a generic algorithm in custom biz apps when, by your own admission, you've avoided features like higher-order functions which allow one to make algorithms more generic? -DavidMcLean?
- You haven't shown them doing such for real CBA apps with inspect-able source code. You only claim it. Claims are not worth a whole lot because they are easy to come by, like soil.
- It's obvious that higher-order functions can make algorithms more generic, and that's been demonstrated as a general pattern on pages such as HofPattern. Unless your custom business apps have no algorithms in them, they can benefit from increased abstraction and genericity, and tools such as higher-order functions enable this. -DavidMcLean?
- This is full of vague, brochure-like drivel. You are being evasive. I see no attempt to explain the necessary details in order to analyze this properly. (Reworded to be slightly less rude.) -t
- Brochure-like? Really? The general concept I'm talking about has already been explained, with code examples, on HofPattern. To reiterate, almost all applications will at some point require some sort of algorithm; this might be a sorting routine, or DijkstrasAlgorithm, or a scheduling algorithm, or whatever. Now, one can implement the whole algorithm every time it's needed. Obviously, it's possible. But you don't really want to write the same algorithm multiple times, because you'll need to debug it multiple times, and you'll have that much more code to maintain. So instead, we try to write the algorithm itself generically, accepting customisation through its arguments. It only needs to be debugged in one place, there's only one implementation to maintain, and if no problems arise that code can be stored in a common library and left untouched. It's much better. -DavidMcLean?
- Sounds wonderful on paper. I'd like to see the actual variations in actual code and how they are actually managed and stand up to actual change so that we can we can count the actual variations, the actual number of algorithms, the actual number of "comparator" variations, and the actual count of combinations of the two and the actual number of lines of code that has to change when actual new variations or actual new combos come along or actual changes to actual existing algorithms and related actual parametric variations. That's the kind of meat we need to really compare to the alternatives. You are just showing a picture of the box. We need to open it up and take a bite out of the burger inside. What are the variations, how are they likely to change in the future, what are their relationships to each other, etc. If nothing ever changes once written, then likely the CASE statement is just fine, for example. There's a lot of ways to split up the "algorithms" or processing and to facilitate variation management. HOF's are not the only game in town. And, are these variations/combos going to be encoded in the source code, or encoded in a database so that they are at least partially managed through "feature panel(s)" CRUD screens? (Which we get into below.)
- I'd love to show you actual code samples, but unfortunately I don't actually know how a scheduling algorithm looks (to be fair, you don't either), and you consider other examples outside the custom biz domain. If another wiki-editor is more familiar with scheduling algorithms than I, could said editor provide some code examples please? -DavidMcLean?
- I didn't select that scenario to analyze. I assumed/hoped whoever did would give us more details, but that doesn't look to be the case (NPI). -t
- I have an employee allocation system (i.e., you over here will do this, and you over there will do that -- which is often a component of scheduling and subject to the same basic conditions) that is as illustrative as scheduling but simpler and unencumbered by intellectual property issues. Over the next few days, I'll dig it up and post it. [...a few hours later...] I found it. I think it will be ideal, as it's based on a genetic algorithm (thus covering the re-usable algorithm part) and uses an RDBMS (which should keep Top happy that it's not avoiding databases). It's written in PHP and Java, but the PHP bits are just for data entry and monitoring so I'll leave them out. The important bits were written in 2005 in Java, using a conventional OO approach. I'll present that, but for comparison purposes I'll also present a version converted to Javascript using HigherOrderFunctions.
As far as sorting and compiling, that's a language-specific issue. Static languages are going to be pickier about new stuff than dynamic ones and there are many diff strategies a language can take. Usually such a change would accompany other changes anyhow, such as a new screen with the parameters/settings for the new algorithm usage or sub-instance (at least in the emp. scheduler app). Thus, recompilation would likely be needed anyhow.
If the basic algorithm is designed properly, it will never need recompilation. C/C++'s qsort() function is used in thousands of applications, on all the canonical data types and hundreds of custom types and data structures, and it never needs recompilation. More complex algorithms used in business -- like employee scheduling, logistics routing, costing, financial calculations of all kinds, etc. -- can use exactly the same HofPattern.
- That's SystemsSoftware, and I've already agreed HOF's may do better there.
- qsort() is SystemsSoftware, but employee scheduling and so forth can use exactly the same HofPattern. Does that make them SystemsSoftware too?
- Sorry, I don't see that pattern very often in actual CBA's. And the few times it happens, CASE, Eval, OOP, and/or databasing can cover it.
- The above describes an example of it. Is it perhaps the case that you don't see it because you've forced CASE, Eval, OOP (you? really???), and/or databasing into a place where they didn't fit as well as a HigherOrderFunction?
- Depends on how "fit" is measured.
Long or frequently-changing switch/case lists are usually a sign that the application is designed wrong, most commonly that something should be put into the database or a config list instead of hard-coded. Non-trivial
feature additions usually "touch" many other aspects and parts of the application, and one cannot know which they will touch in advance because each change request is different. Things just don't grow in the plug-and-play-a-HOF
HofPattern kind of way in the real biz world (unless you are doing something really wrong). Of course, you can prove me wrong by producing actual or realistic HOF "lists". It looks to me like yet another case of a snazzy lab toy choking on reality, like those OOP shape & animal examples that used to trick naive IT managers into producing really goofed-up OOP apps by forcing everything into a tree taxonomy (until GOF came along with even screwier OO patterns to "fix" the trees).
Yes, long or frequently-changing switch/case lists are bad. HOFs make it possible to avoid this problem, as I described above. Also see above for a realistic example which is based on suitably-anonymised actual business events.
Usually you don't have 30 very different "algorithms", but rather start to see commonality among algorithms such that it starts to resemble example "Pete-82" shown in HofPattern. It's then re-factored for the various sub-features to be triggered from configuration "switches" in ControlTables that are maintained by users or power-users (usually via GUI/CRUD screens in mature apps). This is how most biz "algorithms" grow in my experience, not "straight out" as you seem to assume or pretend. They grow "wide" as much as they grow "tall".
Maybe you are just a poor algorithm factorer, or somehow end up serving the role of "power user" instead of let an actual power user control the sub-features (stored in the database). It may be possible to control such sub-features by using combinations of HOF's, but that's not the proper way to design biz software unless job-security is the primary goal and you want to put power-users out of a job so that you are paid instead of PU.
It's been pointed out very clearly above that there aren't "30 very different 'algorithms'". This has all been discussed in detail and at great length in HofPattern.
(Complaints about writing style have been moved to HomelessContent, and some of the wording of the above has been adjusted in an attempt to compensate for the removed content. If I accidentally altered the meaning, my apologies.)
In HofPattern, you seem to dismiss the Pete-82 pattern as "data-driven", "reports only", and "non-algorithm-oriented" (paraphrased). In other words, if the programmer is controlling the sub-features via combo's of HOF's, then it's "high level algorithms"; but if a power user is controlling it via feature screens or ControlTable(s), then it's "grunt data-driven stuff" (paraphrased). Please review and clarify your stance.
I see no problem with HOFs internally executing scripts or other direct-able content defined by power users. I see no problem with power users writing scripts that use HOFs. I know power users who happily write sophisticated Javascript. At some point, the distinction between programmer and power user isn't distinguishable.
- That's a risky practice for at least two reasons. First, they may put something in the code that may crash the program or system etc. Second, they may find another job and the next power user to take over may not be comfortable writing programming code and HOF's. It would not be acceptable to the managers of most projects I have worked on. Like I've suggested at before, we do have to more or less cater to the lowest common denominator of user (or LCD of power-user in some cases) because a user who can't use the system outright generates more "friction" than a gifted user who is slowed by a mundane interface. The first outright stops production while the second one just generates whiny noise. The organization will generally prefer reduced efficiency over a reasonable possibility of stopped production if their next hiree is not as swift as they hoped. Plus they have to pay more to get a scripting power user. I would roughly estimate a scripting requirement adds almost 10k/yr to their salary (USD). They qualify as "programmers" (perhaps "entry level"). The relationship you talk about is more akin to lead programmer (you), along with "staff programmers" being what you are calling "power user". -t
- Aren't power users, by definition, not the lowest-common-denominator of user? They're the opposite to that. As for "they may put something in the code that may crash the program or system", sure, they could. So can the programmers. If you don't trust your users, apply sandboxing to the scripting access you give them, or just don't give them access. But why don't you trust your users, considering this is an in-house system? -DavidMcLean?
- Note in parentheses it says, "or LCD of power-user in some cases". It's not really a matter of me trusting them, it's what best fits with the given organization's expectations, or a typical organization if no specific direction is given on that issue. It's generally not realistic to expect the power users to consistently be coders, including when replacements are hired. I generally consider a "power user" to be one who knows their way around the minutia of a given application and its "project configuration" screens or rule-builders for domain projects/objects. For larger and government organizations, it may also create HR and legal headaches because if they are coding, then they may ask to be re-classified as "programmers", and perhaps even ask for back pay. And some newbie programmers can indeed be dangerous if they are aggressive enough to mess around with source-code outside of their immediate concern. The importance of longer-term maintenance issues sometimes escapes them. Sandboxing may be in order for such. If you get called into the office a few times during your Sunday nap or 3am to fix one of their "experiments", you may start to appreciate some sandboxing.
There you appear to be at first suggesting that one use combo's of functions and/or HOF's to make use of or share the commonality of the algorithms in the "list". (See where you stated, "and compose functionality as and where needed from behaviourCommonToAll(), blah(), moof(), znig(), grob(), and fibble()") However, what I am proposing is that you make it possible for power-users to control the switching on/off and/or the order of these sub-parts rather than a programmer. Your group of functions is essentially a
DomainSpecificLanguage. I'm simply
moving the business of re-composing of those sub-elements to the power user instead of the programmer (this "config" is stored in the DB). It's not "less algorithmic" or "less
ComputerScience", it's just differently algorithm-atized.
I don't see how providing scripting to end users changes anything.
See above regarding level of "power user".
Note that C-style switch/case statements are unnecessarily complicated and fragile. See IsBreakStatementArchaic.
CategoryFunctionalProgramming
JanuaryThirteen