Skip to content

Instantly share code, notes, and snippets.

Created January 15, 2016 16:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/2ee61927820fb35997d8 to your computer and use it in GitHub Desktop.
Save anonymous/2ee61927820fb35997d8 to your computer and use it in GitHub Desktop.
Slack Log from cfml-general
2016-01-14T12:54:21Z @thubbard29 @ has joined the channel
2016-01-14T13:02:53Z @aaronstoddard I%27m having a time getting a PO-Box detection regex to work. Anyone have a working RegEx for this? I%27ve tried several attempts but I%27m apparently still mourning my loss of the Powerball this morning. <http://trycf.com/scratch-pad/gist/ad131399ac24b23e09bb>
2016-01-14T13:13:31Z @aaronstoddard I%27m updating the gist as I try alternatives. So far I have one regex that covers 75% of my test cases.
2016-01-14T13:14:22Z @tbrown looking for general feedback/resources in making sure the model layer of my application is structured in a standard way that will produce a solid service layer. Is there a good resource as to what should be included in the service layer %28simple api that invokes a DAO layer, etc? I understand this is a highly subjective question, but was curious if anyone had some examples of how they create their service/dao layer so I can improve my code organization and re-usability.
2016-01-14T13:15:58Z @aaronstoddard <http://objectorientedprogrammingincoldfusion.com/> &lt;-- A good book for that purpose.
2016-01-14T13:16:44Z @aaronstoddard Are you using any frameworks? Using Dependancy Injection?
2016-01-14T13:18:18Z @aaronstoddard For my own projects, My model folder is divided into feature folders:
/model/authentication/authenticationObj,authenticationGateway,authenticationService
2016-01-14T13:18:33Z @tbrown yeah it%27s a coldbox application, but figured the question might be more broad reaching so thought i%27d throw it out here..
2016-01-14T13:22:14Z @watney
2016-01-14T13:22:14Z @johnsieber @ ++ thanks for sharing as well%21
2016-01-14T13:22:39Z @tbrown i%27ll definitely pick up a copy of that book, but is there are general rule of thumb that the service only knows about other services and the gateway is only ever invoked by the service of the same feature?
2016-01-14T13:23:27Z @aaronstoddard As OOP pattern that is the generally accepted method.
2016-01-14T13:23:57Z @aaronstoddard Gateway %28and/or DAO%29 is specific to its objects data persistence layer.
2016-01-14T13:25:49Z @elpete Just saw the regex conversation above, and it made me think of <http://verbalexpressions.github.io>.
I started one for CFML if anyone is interested in contributing: <https://github.com/elpete/CFMLVerbalExpressions>.
You can install via ForgeBox: `box install VerbalExpressions`
2016-01-14T13:26:31Z @bunniez hello friends. i am trying to write a self-submitting form for the first time. at the top of the page i have &lt;cfif isDefined%28#form.empID#%29&gt; where empID is one of the inputs. . . . but after adding that now i can%27t load the page without getting the error: "Element EMPID is undefined in FORM."
2016-01-14T13:26:35Z @aaronstoddard So only the object knows its gateway functions%28if you inject the gateway into your object%29 or you could inject your gateway into your object specific service and have the service manages the interaction between the object and the gateway.
2016-01-14T13:27:23Z @aaronstoddard @k Sound like you need to param the empID value.
2016-01-14T13:28:25Z @aaronstoddard either cfparam form.empID=0 or &lt;cfparam empID=0&gt;
2016-01-14T13:29:52Z @bunniez thank you, cfparam fixed it. not sure why no tutorial i checked online said that was required.
2016-01-14T13:30:01Z @bdw429s @K `isDefined` takes a string that contains the name of the variable, not the variable itself.
2016-01-14T13:30:18Z @bdw429s `cfparam` will NOT work if you are checking to see if it%27s defined%21
2016-01-14T13:30:28Z @bdw429s You want `isDefined%28 %27form.empID%27 %29`
2016-01-14T13:31:14Z @johnsieber or structKeyExists%28form, "empID"%29 will work as well
2016-01-14T13:33:44Z @watney
2016-01-14T13:33:44Z @tbrown @ ++ thanks.. I think I%27m on the right track, just trying to get my mind around the best practices... so the service layer needs to stay as generic as possible to make the api the handlers %28and other services%29 use be as agnostic as possible. Just didn%27t know if there was a way to structure my model to accomplish this with only a "bean" and a service. It sounds like if I add the gateway layer this allows my service to be more of a proxy for the business logic which further hides that complexity from the consuming application.
2016-01-14T13:34:40Z @bunniez @ THANK YOU, adding the single quotes actually fixed it for real. cfparam got rid of the explicit error but was causing some kind of logical error.
2016-01-14T13:38:10Z @bdw429s @ You%27re going to want some kind of data access layer unless you%27re using ORM. Gateway is really more of a CF-thing with the initial though that your DAO returned a single object, but the gateway was for multuiple records. I never bothered with the distinction and always used DAO in my non-ORM projects.
The really only hard-fast rule is to find what works best for you and your team, and creates a well-organized and manageable code base. _Always_ keep in mind that is your prime directive.
My second rule of thumb was
&gt; Fat beans, thin services, and thinner controllers.
Creating and testing your model objects first before ever wiring it into a handler forces you to keep that business logic where it belongs.
2016-01-14T13:42:50Z @watney
2016-01-14T13:42:50Z @tbrown @ ++ thanks.. i think that makes sense. Like you said this highly dependent on what works best for the particular project, but when you say Fat Beans what would be an example of extra methods that you would add to the bean? getFullName%28%29 to concat fname and lname? and then in your service do you just inject wirebox and create the DAO object in the service? maybe i%27ll :redirect: to <#C06TSRXCJ>
2016-01-14T15:07:57Z @miguel-f @ In case you have not seen it, learn CF in a week is probably the best %28only?%29 tutorial out there for CFML. <http://www.learncfinaweek.com/>
2016-01-14T15:21:30Z @bunniez @ thanks, i did poke through that a bit, typically my job keeps me so occupied that i%27m kind of learning as i go between online toots and the manuals.
2016-01-14T15:22:48Z @seancorfield @ Yeah, that whole DAO/Gateway separation thing was probably "my fault" as I introduced it in "intro-to-OOP" material for CF about 10-13 years ago, thinking the "rule" of separation would help CFers migrate to OOP more cleanly %28keep queries in the Gateway, keep single Object persistence in the DAO%29. But a lot of people treated it as gospel rather than just a starting point. And stuff like Illudium P-38 solidified it. And then we had the 5:1 anti-pattern all over CFML code :frowning:
2016-01-14T15:24:25Z @bdw429s @ I still remember your article on the anemic domain model in the fusion quarterly :simple_smile:
2016-01-14T15:24:40Z @tbrown Thanks @seancorfield do you have an example of what you would recommend instead?
2016-01-14T15:25:14Z @seancorfield The best advice is that Fusion Authority article but I don’t have the source %28or the rights to republish it%29.
2016-01-14T15:26:02Z @bdw429s Man, I used to have a copy of it...
2016-01-14T15:26:34Z @tbrown Just trying to get away from the 5:1
2016-01-14T15:29:16Z @seancorfield FYI <http://corfield.org/entry/The_DAO_and_Gateway_separation_in_CFML_is_nonsense> %28from March 2009%29
2016-01-14T15:30:10Z @seancorfield And the background to it <https://groups.google.com/forum/#%21msg/cfcdev/WsyNC-umibE/AxSAtVOafeMJ>
2016-01-14T15:31:32Z @seancorfield You can read a teaser of the Fusion Authority chapter here: <http://link.springer.com/chapter/10.1007%2F978-1-4302-7214-4_21#page-1>
2016-01-14T15:36:46Z @clockworkrebel What is the 5:1 antipattern?
2016-01-14T15:37:10Z @seancorfield Bean + DAO + Gateway + Service + Controller for every single domain object.
2016-01-14T15:37:16Z @clockworkrebel Ah
2016-01-14T15:37:47Z @seancorfield So if you have 20 DB tables, you’d end up with an app that has close to 100 CFCs :frowning:
2016-01-14T15:38:01Z @seancorfield I’ve seen that in production code… horrific...
2016-01-14T15:38:30Z @seancorfield I actually saw a Mach-II app that pretty followed that anti-pattern and it had %2A200 database tables%2A OMG%21%21
2016-01-14T15:40:01Z @clockworkrebel I%27m sorry to sound like a child here, but what%27s a bean? Is that the same as or similar to a "javabean"?
2016-01-14T15:41:52Z @watney
2016-01-14T15:41:52Z @tbrown @ ++ thanks for the links I had read them and made me realize i needed to do something different...so i guess i still have a lot of reading to do, but what are the layers you are advocating instead? bean %28object centric vs table%29 and DAO for interacting with a grouping of beans and services that bring the logic together into a larger unit of related functionality?
2016-01-14T15:42:19Z @seancorfield Turns out I have the raw source of the article here <http://corfield.org/articles/beans_etc.pdf> — no images, just text / unformatted.
2016-01-14T15:42:27Z @clockworkrebel oh maybe I should read those links =P
2016-01-14T15:42:31Z @seancorfield Not sure how valuable that is without the illustrations.
2016-01-14T15:44:07Z @seancorfield @ loosely a "bean" is most often a "domain object" but in the context of a "bean factory" %28dependency injection a.k.a. inversion of control%29 all managed objects are "beans"… some are transient %28usually the "domain objects", which also have a persistent representation in the database%29 and the rest of singletons %28services of various sorts%29.
2016-01-14T15:45:43Z @seancorfield If those terms don’t help clarify then I’ll suggest Google for the basics...
2016-01-14T15:45:59Z @clockworkrebel thank you @seancorfield I%27m reading your linked pdf right now. I believe we use these things where I work, but perhaps don%27t use the right terminology
2016-01-14T16:09:44Z @clockworkrebel wow that article was really interesting, and now I have some stuff to think about
2016-01-14T16:15:18Z @tbrown @ so if understand what your article is saying.. Our beans %28business objects%29 should be more than just simple data containers for a single row in a table, but instead be enriched with logic that manipulates its own data. Then our data access objects should be more generic and not so tightly coupled to a single table but ecapsulate the data access layer %28typically SQL%29 for acting on the data stored in functionally related business objects. And services are used to provide a more generic facade to our data gateways?
2016-01-14T16:19:24Z @clockworkrebel I got the idea that the DAO would be tightly coupled with the underlying table%28s%29 but that this was ok, because the business objects could in a sense stand on their own, and if you had a change to the way data was stored, you would only have to rewrite %28or modify%29 your DAO
2016-01-14T16:19:37Z @clockworkrebel but maybe I misunderstood
2016-01-14T16:22:28Z @seancorfield @ In an "ideal" OOP system, your domain objects contain nearly all of your business logic — "service" objects exist only to orchestrate operations across multiple domain objects.
2016-01-14T16:23:06Z @tbrown no i likely didn%27t phrase my summary very well.. i think you are correct.. but the key is to stop thinking about tables and think about business objects.
2016-01-14T16:25:53Z @seancorfield Database tables are "just an implementation detail" of how objects are persisted. A domain object might actually be stored in multiple related tables. Similarly, a single DB table might actually contain multiple types of domain object.
2016-01-14T16:27:27Z @tbrown so it%27s ok to think of a domain object %28bean%29 as having many properties that span multiple tables.. then when i pass it a rich domain object the DAO layer splits that object into it%27s underlying homes in the db..
2016-01-14T16:29:01Z @tbrown likely just rephrased what you just wrote but trying to wrap my head around this giant 5:1 explosion and reduce the amount of objects I have to think more about the business logic of it rather than my objects being a direct mapping to my database tables..
2016-01-14T16:30:18Z @clockworkrebel Now that i%27m thinking about it, it%27s really important that the DAO be able to split a domain object into many tables. Imagine the terrible schemas that we would come up with if the penalty for creating another table was to have to create 4 or 5 new components%21
2016-01-14T16:33:58Z @clockworkrebel Thinking about it further, I guess that%27s what this is all about, and in a sense, why this 5:1 antipattern is in fact an antipattern
2016-01-14T16:34:22Z @clockworkrebel So maybe that was more of a platitude than a realization =P
2016-01-14T16:38:10Z @jtreher You can also imagine that you are using a relational storage system such as oracle and then you for some reason are able to switch to a flattened document store such as Mongo for this particular object%27s persistence. You should still be able to call datalayer.save%28%29 from within your business object. If you had it setup correctly, you would not have much to change.
2016-01-14T16:41:42Z @tbrown so you call `datalayer.save%28%29` from within the business object %28bean%29? so you are injecting the data layer into the bean? I%27m sure i%27m being obtuse.. too many trains of thought
2016-01-14T16:42:25Z @jtreher Yes, you can inject the data access object%28s%29 and service into the bean. It%27s pretty awesome.
2016-01-14T16:42:53Z @jtreher All of Sean%27s hard work.
2016-01-14T16:43:37Z @seancorfield Our pattern tends to be `myDomainObject.save%28%29` and have `DomainObject.cfc`depend on the persistence service so it can do: ```function save%28%29 {
variables.persistenceService.save%28"DomainObject",this%29;
}```
2016-01-14T16:44:00Z @clockworkrebel Yeah I guess the idea is that the bean needs to be able to save itself. And it%27s allowed to know that it has a datalayer, just not how that datalayer works
2016-01-14T16:44:20Z @seancorfield A controller would typically need to call a service to domain objects to work on, but then could just tell them to save themselves when the controller is done.
2016-01-14T16:45:10Z @seancorfield At World Singles, we have a data mapper that transparently deals with both MySQL and MongoDB so our application code doesn’t need to know how domain objects are actually stored.
2016-01-14T16:45:22Z @seancorfield %28I published most of the data mapper on GitHub%29
2016-01-14T16:47:14Z @tbrown k. i%27ll check it out, definitely have been hunting for good examples of this design pattern so I can overlay it onto my business logic.. appreciate the help.
2016-01-14T17:02:07Z @tbrown are there any other good examples of this somewhere on git hub unless i%27m missing it in the datamapper repo.
&gt; Our pattern tends to be `myDomainObject.save%28%29` and have `DomainObject.cfc`depend on the persistence service so it can do:
2016-01-14T17:50:27Z @seancorfield <https://github.com/seancorfield/datamapper/blob/master/Bean.cfc#L272-L288>
2016-01-14T17:50:38Z @seancorfield Specifically <https://github.com/seancorfield/datamapper/blob/master/Bean.cfc#L277>
2016-01-14T17:51:07Z @seancorfield Note that we track dirty vs clean fields so we can run an update on just the dirty fields.
2016-01-14T17:51:56Z @seancorfield All of the MongoDB/MySQL magic happens in `WS.data.save_row%28%29` — which is written in Clojure but could have been written in CFML %28it would just be slower in CFML%29.
2016-01-14T18:02:01Z @tbrown so your domainObject extends the Bean.cfc?
2016-01-14T18:04:20Z @tbrown i reread the readme.md i think it%27s making more sense.. appreciate the patience on this one.. trying to put together a quick example app outside my larger app to test out these concepts so I can grok everything
2016-01-14T18:18:55Z @seancorfield Yeah, sorry, it’s all very generic. If we need anything beyond bare persistent data, we have a `foo.cfc` that extends `Bean.cfc` and have all the domain logic in that child component.
2016-01-14T18:19:40Z @seancorfield Similarly, we have `BarService.cfc` that extends `BaseService.cfc` to provide common, low-level persistence operations for the core type manipulated by the server.
2016-01-14T18:22:04Z @tbrown appreciate the help and i understand a lot of the answers are it depends, just trying translate this to User.cfc UserDAO.cfc and and User.cfc would have the DAO injected into the bean via wirebox could you explain the `.save%28"DomainObject",this%29;` this represents all the current domain object and the quoted portion is just so it know what type of object `this` is?
2016-01-14T19:03:37Z @jtreher You are in deep now%21 It%27s some kind of magical bean. The easiest way to learn it is to explain it to your coworker with a working example.
2016-01-14T19:04:56Z @seancorfield "and the quoted portion is just so the `save%28%29` method knows what type of object `this` is?" — yes, at a basic level. If you have a generic data layer, when it is passed the data to be saved, it also needs to know how/where to save it.
2016-01-14T19:05:51Z @seancorfield There are several possibilities. You could, for example, have `bean.getTableName%28%29` always defined and have the data layer call that %28in which case you don’t need to pass it in, just the bean reference itself%29.
2016-01-14T19:06:15Z @seancorfield But then why would other code need/want to know/access the table name for a given object?
2016-01-14T19:08:12Z @seancorfield So the approach we’ve taken is to explicitly tell the data mapper where to store/load the data %28which we keep in `variables.name` — and we don’t use standard get/set functions — ours are smart enough to know about `variables.data` %28original, read-only data, loaded from the data store%29 and `variables.dirty` %28writable, updated data, changed since last load/store operation%29.
2016-01-14T19:09:07Z @seancorfield so, for us, `bean.getFoo%28%29` is handled by `onMissingMethod%28%29` which calls `bean.get%28"foo"%29` which by default checks `variables.dirty` for a recent value else checks `variables.data` for the original value.
2016-01-14T19:10:35Z @seancorfield Similarly, `bean.setFoo%28blah%29` routes thru `bean.set%28"foo",blah%29` which does `variables.dirty["foo"] = blah`
2016-01-14T19:11:45Z @seancorfield It’s actually a little more complex than that %28we track the clean/dirty state of an object and we also record whether an object is empty or "loaded" with data%29… and all our beans can act as iterators over arrays of structs as well as just a single object wrapped around a struct.
2016-01-14T20:36:27Z @tbrown Thanks Sean. But if I can%27t abstract it that much or just want the control on a per object level it%27s perfectly acceptable to have a DAO for each object or is that trending back to the antipattern?
2016-01-14T20:38:07Z @seancorfield I would probably try to stay away from the 1 DAO : 1 Domain Object setup and have a Data Gateway %28or Data Access Object — they’re really just different names for the same concept%29 for each group of closely related Domain Objects.
2016-01-14T20:38:35Z @seancorfield So maybe a UserServiceGateway would know how to saveUser%28%29, loadUser%28%29, updatePermissions%28%29 and so on.
2016-01-14T20:39:35Z @seancorfield The reason for that is that when you ask the Gateway for queries / reports you’re likely to be working with a related set of tables %28user, permission, group, etc%29.
2016-01-14T20:39:57Z @seancorfield So this keeps the conceptual domain language of your problem space consistent with your code organization
2016-01-14T20:41:11Z @tbrown Ok thanks.. And the userDataGateway is injected into the bean? For things like %27dao.saveUser%28 this %29;%27
2016-01-14T20:45:32Z @seancorfield Yup… so `UserDAO.cfc` or `UserDataGateway.cfc` or `UserGateway.cfc`… whatever you prefer. And the appropriate `property` declaration in the `User.cfc` bean.
2016-01-14T20:45:55Z @seancorfield %28assuming you’re using a DI/IoC framework%29
2016-01-14T21:08:18Z @tbrown Yes %28wirebox%29. Thanks for the back and forth on this. Very helpful%21
2016-01-14T21:14:48Z @seancorfield Always happy to talk about architecture, OOP, and FP stuff%21
2016-01-14T21:52:44Z @jroberson @ has joined the channel
2016-01-15T06:54:18Z @fmdano I think this is still work posting here, not water-cooler -- slack integrating Skype calling into app: <http://techcrunch.com/2016/01/14/you-can-now-kick-off-a-skype-call-from-slack/?ncid=rss&amp;utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=sfgplus&amp;sr_share=googleplus&amp;%3Fncid=sfgplus>
2016-01-15T07:03:15Z @yogidevbear That%27s cool. I really like the screenhero integration. Similar idea. And screenhero is really cool%21 Two cursors on the same monitor and all that jazz
2016-01-15T08:31:57Z @dvsweden @ has joined the channel
2016-01-15T08:38:23Z @dvsweden Hi all,
I hope this is an appropriate question for this forum. If not apologies and can you point me to the correct area?
I am seeing a very strange behavior on installs. One all of my recent installs the default Java File encoding is getting set to ASCII
Screen shot: <http://screencast.com/t/jcFufr6APb>
On my test box the default is UTF8 – which is what I want, and which according to all the documentation I have found is what CF should be using by default.
Any ideas on where this would be getting picked up from? There are no –D options being added anywhere to override, the LANG and all the LOCALE settings are all identical on all boxes %28UTF8 settings%29 I am not finding anything that should be causing CF to pick up ASCII. I know about using -D to try and override the ASCII setting but my question is why is that getting set in the first place?
I am on Red Hat 2.6.32-504.8.1.el6.x86_64 – CF 11 patched up to HF7 – 64 bit.
Any help would be appreciated%21
2016-01-15T08:53:35Z @salted what is this, a screenshot for ants?%21
2016-01-15T08:53:44Z @salted might want to try the <#C06TABBT8> channel @dvsweden
2016-01-15T09:15:54Z @adam_cameron Just noticed "they" are blocking <http://screencast.com|screencast.com> here.
2016-01-15T09:50:30Z @chris-hopkins @ stick it to the man%21
2016-01-15T09:50:50Z @adam_cameron ha
2016-01-15T09:51:07Z @adam_cameron Our local sysop agreed the move was "lacking in thought"
2016-01-15T09:51:35Z @adam_cameron But equally "not being able to see a screenshot on the CFML slack channel" is not something we can use as grounds for revisiting
2016-01-15T10:17:54Z @dawesi Must be a small issue then...
2016-01-15T10:19:49Z @salted dear god
2016-01-15T10:20:04Z @salted did...did you just react to your own comment?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment