4 ms·
:) Well, it's pretty ugly now that expressions exist, however prior to expressions it was quite nice since S expressions is all they are and I've had this for n
by gnaritas 10y ago
:) Well, it's pretty ugly now that expressions exist, however prior to expressions it was quite nice since S expressions is all they are and I've had this for nearly a decade in .Net, long long before such niceties like expressions existed. And I'll just bolt expressions into my library when I feel like it and type this
var dogs = Dog.FindAll(each => each.Age == null && each.Id == guid);
rather than relying on an external dependency that doesn't work the way I want. The need to do this...
db.Select<Dog>
Use generics at the method level, I find intolerably ugly when you could have created db with said type and have access to an already typed API. What you're doing there, I personally consider bad design and would refuse to use. When I use a typed list... I don't go
someList.Add<Thing>(aThing)
Because the decision to type the list was done at list creation time. Forcing me to pass a type on every call to the db, less than attractive. The best uses of generics don't look like you're using generics because you only have to do this once
class Dog : Persistable<Dog> {}
To have a perfectly typed class side API that doesn't shit generics all over the client side code. The T is specified once and only once, and never seen again and now all the Select/Save/Delete/Create methods no longer require the client to constantly type <Dog> every time they touch your lib.
In all fairness however, it would be trivial to wrap your lib in a persistable template and achieve exactly the API I wanted, should I ever desire to do so. Which is actually a much better argument for using your lib than any you've given.
- mythz 10y ago> Use generics at the method level, I find intolerably ugly Then you shouldn't be using .NET, generic methods are extremely common and especially elegant here since it can work with any POCO which can also be reused elsewhere in any library that works with POCOs. The Generic method is what enables the Typed API without adding any artificial artifacts and wrappers. It's intuitive as to what the lambda is typed to and what value is returned - it's definitely more idiomatic and much preferred over Active Record implementations. In your Example `Dog` ends up being a .NET 1.0-style non-serializable bloated Active Record inheriting from a heavy base class that's non-reusable and coupled to your implementation that you're forced to create for each Type you want to use. It's also not clear what DB connection is being used, what its life-cycle is and whether it's being reused across different types, how you can create transactions spanning multiple types, etc - in Micro ORM's its clear, you use the same db connection to query any Type. There's a reason why most modern Micro ORM's are mapping to clean disconnected POCO's and don't force unnecessary wrappers for legacy inhibitive abstractions like this.
- lenkite 10y agoI believe the above poster was saying that you can have your cake and eat it too by making sure that the type is passed at the time of the DAO construction so to avoid the need of specifying the type at every method. You can still use a common interface and you don't need to follow a 'bloated active record' style for just doing this.
- gnaritas 10y agoCorrect, glad someone understood it.
- gnaritas 10y agoGenerics can apply to classes, not just methods, as you can see in the typed lists included in the framework, you can use generic methods without them taking generic params as you can get the generic param from the class itself resulting in vastly cleaner use of generics akin to the built in typed lists. Look at a typed list, that's the "clean" way to use generics, note it looks nothing like your ORM's interface. > In your Example `Dog` ends up being a .NET 1.0-style non-serializable bloated Active Record Incorrect, active records are perfectly serializable, not the least bit bloated, and I'm not "forced" to do anything, I'm using the interface I prefer having worked with every pattern under the sun for nearly two decades including repositories and POCO's. You aren't showing me anything I don't know, I understand deeply what your lib does and why it works the way it works: I'm disagreeing because I disagree, not because I don't understand something. > It's also not clear what DB connection is being used, what its life-cycle is and whether it's being reused across different types, how you can create transactions spanning multiple types, etc - Of course it's not clear to you how everything else works when we've only seen a single select example, you're making all kinds of assumptions here without cause. None of those things are clear in yours either from the select example shown here. It's only clear when you go read your full page of examples; as I haven't given a full page of examples, this critique is just silly. > in Micro ORM's its clear, you use the same db connection to query any Type. Active record is a micro ORM as well, and I understand all of those semantics about my ORM just as you do about yours. Perhaps you should refresh yourself on what a micro ORM is. > There's a reason why most modern Micro ORM's are mapping to clean disconnected POCO's and don't force unnecessary wrappers for legacy inhibitive abstractions like this. Yes there is, preference of the ORM writers, nothing more. Your preference for POCO's is nor more or less good than someone else's preference for active records; I've written code in every ORM style and I'll take a good old active record pattern over a repository pattern every time because at the end of the day, it's just more pragmatic and allows me to get more work done in less time while writing better looking code. Both patterns are valid patterns, your dismissal of non repository patterns is sophomoric. I've been there, I used to think repositories were so vastly superior, then I grew up and had to hire and train other people and found the ability to get others to understand what's going on overrides my obsession with OO perfections. Active records are practical, they're why Ruby on Rails got so huge so fast. Ignore this pattern at your own peril.
- flukus 10y ago>When I use a typed list... I don't go >>someList.Add<Thing>(aThing) Implicitly you do.
- gnaritas 10y agoExplicitly I don't because the container has already been specialized to a type at construction.