Summarized using AI

Convenience vs Simplicity

Piotr Solnica • June 27, 2014 • Singapore • Talk

In the talk "Convenience vs Simplicity" by Piotr Solnica at the Red Dot Ruby Conference 2014, the speaker emphasizes the importance of balancing convenience and simplicity in programming, particularly in the Ruby ecosystem. He discusses how the convenience offered by various tools, libraries, and frameworks can lead to growing complexity in code, making maintenance and understanding difficult.

Key Points:
- Introduction to Personal Experience: Piotr introduces himself as a Ruby developer with over seven years of experience, explaining the challenges he faced as projects transitioned from startups to large, complex applications.
- Complexity in Programming: He analyzes the problems caused by complexity that arises from using convenient libraries like ActiveRecord without understanding the underlying intricate mechanics.
- Definitions of Convenience and Simplicity: Piotr distinguishes between convenience—defined as the ability to proceed without difficulty—and simplicity, which is about having clarity and ease of understanding.
- Separation of Concerns: He advocates for handling different concerns, such as validation and persistence, with separate objects rather than bundling them into one, even if that initially seems to increase complexity.
- Data and Behavior: The speaker discusses how using more focused, minimalistic objects can achieve better-defined behavior and less accidental complexity in applications. He compares high-convenience solutions with minimalist tools.
- Relational Model: Piotr explains the relational model's significance, noting that it should not only be about database structures but about how data is managed and structured conceptually within applications. He introduces the Axiom library as an example.
- Implementing Simple Interfaces: The goal is to create a simple way to access and manipulate data using basic principles from set theory rather than over-complicated object models.
- Immutability: He touches upon the advantages of using immutable data structures as a means to prevent complexity and enhance code reliability.
- Pragmatic Advice: While Piotr suggests simpler alternatives to tools like ActiveRecord, he acknowledges that for some situations, especially in established projects, leveraging existing conventions may still be necessary.

Conclusions: Piotr calls for developers to embrace simplicity as a foundational aspect of design, advocating for a thoughtful separation of concerns and cautious use of convenience-focused tools to avoid entrenching unnecessary complexity down the line.

Convenience vs Simplicity
Piotr Solnica • June 27, 2014 • Singapore • Talk

Avoiding complexity is one of the greatest goals in programming. The tools we use, libraries and frameworks, must be helping us in achieving that goal. There must be a reasonable balance between convenience and simplicity as growing complexity is the price we pay for that convenience.

This talk is about seeking simplicity when dealing with data and behavior showing alternative approaches to object relational mapping and persistence concerns.

Help us caption & translate this video!

http://amara.org/v/FGY1/

Red Dot Ruby Conference 2014

00:00:19.259 okay hey it's really great to be here so
00:00:24.550 I'm Piazza Utah my name is so rude because I come from clock off it's a
00:00:30.489 beautiful city in Poland if you've never been to Poland it's real beautiful so I
00:00:35.590 invite you to come we have some rubik conferences as well with also beautiful
00:00:40.629 mountains so it's a really nice country so really quickly about me on a ruby
00:00:48.850 developer you can find some of my open source projects on github and follow me
00:00:54.190 on Twitter I'm so linked everywhere so if you wanted to say you had one job I
00:01:00.190 actually don't I have three so I'm a part of a company called powwow at a
00:01:06.910 Polish Norwegian consultancy I'm also working for victorious which is a good
00:01:13.510 hosting platform that you can host yourself and by the way we were moving to docker it's like eighty percent done
00:01:20.580 I'm also working for a norwegian company called evo which is a chain of fitness
00:01:26.170 clubs with a huge infrastructure built in rails so like before i start i wanted
00:01:32.260 to talk a little bit about like my experience this ruby developer so that you can know where I'm coming from with
00:01:38.560 all this stuff so I started working as a ruby developer seven years ago and in
00:01:44.740 2007 we were mostly working on startups right so every project was greenfield
00:01:49.770 everything was really great right we were using rails we were writing a lot of Ruby code and everything was smooth
00:01:56.440 and just beautiful right but at some point some of those startups actually
00:02:02.050 succeeded right so suddenly we started working on huge a couple of years old
00:02:08.369 Reyes apps and at some point it became a problem right it started to be
00:02:14.530 really difficult to maintain those projects and I started to think why is
00:02:21.069 it so hard to maintain a big rails application right what's the cause of this problem and initially I thought
00:02:29.170 that yeah maybe we could use different patterns maybe we could just use different libraries but really what
00:02:38.709 we've been doing for the last couple of years seems to me like not solving the problem but working around the problems
00:02:45.190 that we have and what I realized is that the cause of this problem is just complexity that we have and all the
00:02:52.450 tools that we are using are extremely convenient so that we can move really fast but we don't think about the
00:02:59.290 complexity that we pull in when we start depending on external product of the gems so when we create a new race
00:03:05.920 project even if you don't include any additional gems it's already a lot of
00:03:11.319 complexity that we have without even writing any code so then we start to
00:03:17.860 actually write some code so we build even more complexity on top of already existing complexity right so it's
00:03:24.459 something we don't think about on a daily basis so today I want to talk about convenience versus simplicity and
00:03:32.310 even though the title of this talk may seem to be a little bit abstract I
00:03:37.420 actually try to make it more concrete however I'm going to start by some by
00:03:44.590 explaining some of those abstract terms so convenience when you look at the
00:03:52.500 definition in dictionary it says that convenience is the state of being able
00:03:59.350 to proceed with something without difficulty right and when you think about it it's exactly what happens when
00:04:05.709 we use our convenient tools like rails and true to remember this one this is
00:04:13.600 from screencast we're dhh showed how to build a block application in your rails in 15 minutes it's pretty famous you
00:04:20.169 probably sell it so this is this is it this is the convenience all the things
00:04:25.330 that we're not doing all the things we're not thinking we're just preceding really quickly with
00:04:30.910 our tasks we're accomplishing our goals really quickly without thinking much about the problems that they're that
00:04:36.670 we're actually dealing with because a lot of those problems are solved by the libraries and frameworks that we are
00:04:42.400 using so on the other hand we have simplicity and again when you look at
00:04:47.860 the definition it says simplicity is the quality or condition of being easy to
00:04:53.320 understand or do and it's a little bit tricky because we often say that
00:04:59.260 something is convenient and like immediately connected with something that's simple and it might be a little
00:05:06.400 bit confusing because you see something that is simple your think okay that's convenient it's simple i can simply just
00:05:11.860 use it and it works but you don't really think about what's inside right so what
00:05:19.600 usually happens is that a lot of libraries and frameworks that are super convenient and really simple to use come
00:05:26.770 with a lot of internal complexity something that we just don't think about because we don't see it so it's not our
00:05:34.780 problem right so when it comes to
00:05:40.120 complexity and ways of dealing with the problem of complexity what program is
00:05:46.540 usually do is to focus on separation of concerns if we have a huge problem which
00:05:54.280 is real difficult to solve we try to like split it into smaller pieces into smaller problems and solve them
00:06:00.940 individually and what I've noticed in
00:06:07.090 the Ruby ecosystem that is probably inspired by by rails we often focus on
00:06:17.290 convenience first we often focus on all the fancy dsl's and the convenience that
00:06:23.080 that should come right from the start so when you look at for example active
00:06:31.150 record right it's a great example of a convenient library a library library
00:06:37.270 that solves a lot of different problems the problems that are really hard to solve by the way so when you look at a basic model the
00:06:44.919 basic active record model it's just an empty class right and you might think
00:06:50.139 that it's super simple right because it's just a class and you don't even have to write anything except defining
00:06:56.079 the class to get a lot of functionality for free if you want to create something
00:07:01.679 and persist it in the database it's also very simple just one method called
00:07:07.809 passing programs and you're done even wanna even if you want to do something more fancy like find something fetch
00:07:15.339 something from the database loaded into memory and then do something with it and
00:07:20.349 save it back to the database it's still super simple you just call like three
00:07:25.659 methods here right so you might think it's all so simple I don't need to learn
00:07:32.709 a lot I'm I'm just reading API documentation for like three minutes and I know what to do so you think yeah
00:07:39.729 that's simple and really I don't think it's simple and the reason why it's not
00:07:45.429 simple is that there are a lot of things going on under the hood and even though I don't see them they do exist and
00:07:52.659 that's why I prefer to use the word convenient because it is all very convenient but it is not simple there is
00:07:59.619 no simplicity here there's a lot of internal complexity it's just we don't see it when it comes to separation of
00:08:09.849 concerns if we look at this create method and think about what's actually
00:08:17.169 going on we will realize that we are
00:08:22.479 dealing with things like data coercion which is a huge problem to solve by the
00:08:28.329 way there are a lot of really nasty things that you need to deal with when
00:08:34.809 you want to have coercion setting default values this is also something
00:08:40.179 that happens under the hood you might not think about it but it exists we do
00:08:45.759 things like validation and validation is also a really big problem to solve and eventually we we do interact with the
00:08:52.899 database and interacting with the data is also a huge problem to solve right and this is like the basic stuff that
00:08:59.800 that happens under the hood and if you're less lucky you could have things
00:09:07.329 like business logic hidden in life cycle hooks all the before say before validate
00:09:13.180 all this stuff this is super complicated and we do that we also do things like
00:09:19.810 handling nested data structures using except nested attributes for which is also super complicated thing to deal
00:09:26.800 with we also do things like data normalization to custom attribute writers and plenty of other stuff so
00:09:34.899 this is a lot of complexity and we tend to hide it in one place but it's just
00:09:42.040 not a good thing to do so when if we want to talk about separation of concerns in this context we might look
00:09:51.339 at it in a way where we can use separate objects to handle separate concerns so
00:09:57.910 what I tend to do these days is to process parameters using a separate
00:10:05.079 object validate things using a separate object and handle persistence by
00:10:10.720 separate separate object as well and whenever we talk about separating concerns and whenever we talk about
00:10:16.930 using separate objects there's always at least one person who would say something like well that's more complicated right
00:10:23.139 I usually have one object now i have three and i don't think it's a good way of thinking about it because separating
00:10:30.339 concerns is actually something that leads to simplicity even though you have more objects you still have better
00:10:37.180 encapsulation and those objects are smaller and it's just easier to work with them and one of the benefits that
00:10:43.990 we have here is that we can always come up with a higher level abstraction something that is more convenient and
00:10:50.529 just encapsulated and have just one method and we have exactly the same convenience but internally it is
00:10:56.649 separated internally we have separate separate objects having separate concerns so this is like the benefit of
00:11:04.860 separating concerns where you don't have to you not necessarily
00:11:09.870 have to be concerned about many things you can have a system that is built on
00:11:15.810 top of more primitive tools but it could expose a very convenient interface but
00:11:21.090 once some of those concerns become your problem when something is is your
00:11:26.310 concern for example when you actually want to deal with corrosion on your own
00:11:31.440 or validation on your own you always have a way of using a separate object
00:11:37.970 whereas in case of libraries like active record or many other gems written in
00:11:43.710 Ruby where a lot of things are handled by by just one thing you just don't have that choice because there's no separate
00:11:50.520 objects there are no separate objects that would handle separate things so you just cannot use them separately so the
00:11:59.760 next thing as a data and behavior this is also an interesting subject because
00:12:05.910 so Ruby is an object-oriented language obviously so whenever we talk about object-oriented design we like to say
00:12:12.570 things like yeah it's all about objects and sending messages right or behavior oh and I think that this whole movement
00:12:20.550 with with design driven development we had a talk yesterday about it it is a
00:12:26.700 nice way of thinking about software but quite often it actually leads to
00:12:32.100 something that we could call accidental complexity we may quite often introduce
00:12:38.970 complexity that it's not really needed just because it feels like good to think
00:12:44.880 about objects and the way they correspond to I know some real world concept like for example if we have an
00:12:52.380 application some kind of a system running and it it has users right so it's like natural for us to think about
00:12:59.600 having a user object because well it will represent it will represent the
00:13:05.220 users of our system so it feels like natural to to to design our system like
00:13:10.470 that but when we do this and when we focus on behavior so much we may often
00:13:16.860 use objects that are simply to be and it's also really something really a popular to do
00:13:27.450 in Ruby and especially in rails to use active record for everything and as I
00:13:35.519 said if you have a user instance and we have users in the real world and we want
00:13:41.459 to have something like displaying full name it feels natural to just add a method called full name because well our
00:13:47.100 our users know their full names so our object should know it's filling right so
00:13:53.010 we do that but we but we don't think about what's the actual requirement and if our feature is too I don't know
00:14:00.620 display a list of users with their full names in some kind of user interface then the only thing that we need is the
00:14:07.110 data and something really simple that knows how to display a full name or how
00:14:12.420 to return a full name right so what we do here is that we already have an
00:14:19.560 object we already have a model and represent users so which is convenient to just just put methods there just just
00:14:27.000 expand its behavior because it feels natural but what I what I'm usually
00:14:33.149 doing these days is to just focus on the most basic stuff on what's really really
00:14:39.329 needed for the system in order to work so the data is really important all we
00:14:47.370 need is to just get the data and have some kind of an object that returns the
00:14:53.220 full name so it is like the essential part here to have just those two things
00:14:58.800 in order to accomplish our task this is obviously a very simple example but it
00:15:04.680 like illustrates the philosophy here and you know using this object is still very
00:15:10.440 simple so um this is pretty much what
00:15:16.820 convenience is well this is like a some kind of a crappy coffee maker but it's
00:15:22.560 convenient right you just press the button and there goes coffee but what I really prefer is this this is v60 I had
00:15:30.209 coffee here from v60 it was awesome this is super super simple very basic tool and it
00:15:37.440 makes an awesome coffee and this is pretty much the sense of the essential
00:15:42.779 stuff you focus on what's really really important and you reject everything else I would even I would even say that
00:15:50.430 sometimes it makes sense to be minimalistic what when you big when
00:15:57.000 you're when you are minimalistic you're you're just reducing complexity and
00:16:02.150 you're just using just the thing that you need nothing else so another
00:16:09.360 interesting thing about data and behavior is similar ability which which
00:16:14.940 is also a little bit weird since Ruby again it's an object-oriented language so we are used to relying on mutable
00:16:21.210 state however mutability is really
00:16:26.240 something that can bite you and be very problematic and here's a very simple
00:16:32.040 example so we have our presenter object it receives some data hash and the fact
00:16:39.930 that this data hash can be changed by something else something external it can
00:16:46.350 actually cause our presenter instance to just be broken and this is absolutely terrible it's just such a basic thing
00:16:54.180 that we do and it can break our code I mean what's the point of doing that so
00:16:59.790 really when it comes to immutability when we're dealing with the data I would
00:17:05.490 really encourage you to just think about making the data structures immutable in
00:17:12.209 a ruby we do that using freeze right unfortunately if we have nested data
00:17:18.240 structures like this data hash we might want to use some external tools tools
00:17:24.360 like ice nine which is a gem that gives you this crazy method called Dupri's
00:17:29.960 which will actually take this hash and freeze everything like deeply so if we
00:17:38.130 try if you try to change it in place like mutated in place it will it will
00:17:43.620 raise runtimeerror all right this is a little bit crazy obviously
00:17:48.750 Ruby but and it's slow and it's actually really slow but for the data structures
00:17:57.000 I'm actually using it and it actually makes my code much more simpler and I
00:18:02.280 feel more confident when I when I'm relying on data structures that don't change another interesting jam that you
00:18:10.200 could use when it comes to immutability is adamantium which is even more crazy
00:18:15.620 it is a gem that makes your objects immutable also by deep freezing them so
00:18:24.570 when it comes to freezing data structures it's one thing but when it comes to freezing all your objects it's
00:18:32.700 a completely different story so I actually started using adamantium a
00:18:38.190 couple of years ago initially when we were working on a date and upper to
00:18:44.850 which is now called Rome we started with like a very clear separation where we
00:18:52.020 have commands and you have Curie methods and it worked great but then then cop
00:18:58.550 maintainer of data mapper and also developer in Rome suggested that maybe
00:19:04.770 we should try to make it more hardcore and actually start to use immutable
00:19:10.380 objects like all the time so he created adamantium to like enforce this style
00:19:15.780 and I get really intrigued by that and I thought well this is a little bit crazy
00:19:21.420 but I'm gonna try right so I started doing that and really it was tough it
00:19:27.810 took me like few months to just wrap my head around this concept and just change my style of writing code so that I will
00:19:34.530 be creating objects that won't have to change and initially I hated it but I
00:19:40.680 really had this like this feeling that it will pay off like at some point I
00:19:46.650 will get it and it will benefit will be beneficial and it actually started to
00:19:52.410 make sense at some point and after a few months I noticed that my code is now way
00:19:58.679 more simpler and I'm actually way more confident with everything that i do because i don't
00:20:04.080 have mutable state so adamantium works more or less like that so if you have a
00:20:11.610 class and you include adamantium them you won't won't be able to change
00:20:18.150 anything inside this this object the instance of this class no more no matter
00:20:23.820 how deeply you will go how deep you will go it will raise an error but it's super
00:20:30.000 slow it's extremely extremely slow so under the hood it's it's using the the
00:20:36.300 ice nine gem that i showed you before but I would actually like to encourage
00:20:43.380 you to just play with it as the next exercise and see how far can you go with it it's a mind shift but I think that
00:20:51.030 it's actually worth the effort because it might change the way you think about
00:20:56.070 writing code it worked really great for me I'm still using adamantium in my some
00:21:01.740 of my open source libraries and in some places in in in in my projects for my
00:21:07.680 clients however it is slow so whenever I see that it slows down things too much I
00:21:14.280 would just drop it but the trick is that after few months of writing held in this
00:21:20.430 style I actually so got used to it that I'm currently I'm just unable to design
00:21:26.820 something when objects are mutable I just my brain no no longer works like
00:21:31.830 that I just created objects and they won't change they don't expose an interface where you can mutilate them I
00:21:38.070 just mind shift seriously so this is
00:21:43.140 something that it's also related to convenience and simplicity because a mutable state is actually convenient
00:21:49.710 because you don't have to think about like you don't have to make many decisions up front you just create some
00:21:56.160 objects and then later on in run in run time they may or may not change depending on the context maybe I will
00:22:02.430 have to do something extra to set some I instance variable or not it's just more
00:22:07.530 convenient whereas objects that cannot change are less convenient but you act
00:22:13.920 Chile achieve simplicity in your code so
00:22:19.470 it is worth the effort I highly recommend that um so next part is about relational model this is a huge subject
00:22:29.840 when we think about when talk about relational model we usually think about relational databases and the trick here
00:22:36.630 is that it's not really about the databases it's not really about SQL
00:22:42.470 because relational model is actually something that we can use to structure our data and recently I read a paper
00:22:50.010 called out of the tar pit which is which talks about dealing with complexity and
00:22:56.630 one of the biggest parts of this paper is about relational model and how it can
00:23:03.270 simplify our systems so the definition
00:23:08.790 that they have is that the rule the relational model has despite its origins nothing intrinsically to do with
00:23:14.820 databases rather it is an elegant approach to structuring data and means to money for manipulating such data and
00:23:20.820 a mechanism for maintaining integrity and consistency of state so when we talk about relational model we actually talk
00:23:28.710 about how we structure our data how our data should look like in our system
00:23:34.530 we're not talking about how it's going to look like in a database it's a separate concern and also it gives us a
00:23:42.750 way to deal with the data in an in a structured manner so when it comes to
00:23:48.210 Ruby and rulership relational model we actually have some pretty awesome libraries so if you want to if we want
00:23:56.640 to use relational model in in Ruby for example we have a library called axiom
00:24:01.730 this is like the foundation for Ruby object mapper and this library gives us
00:24:06.900 a an implementation of relational algebra and with axiom you can define
00:24:12.840 relations and as Luca said yesterday during his dog relations are just sets
00:24:19.770 with tuples and nothing else it's it's a really really simple concept and when we want to define a structure of a relation
00:24:26.820 we simply define its header and a header just defines what attributes a relation has and what data data types we use so then
00:24:36.210 we have a an interface for a manipulation so for example if we have
00:24:43.820 relations users and tasks we can simply insert data into those relations and by
00:24:50.880 the way this this is immutable so users
00:24:55.950 dot insert returns a new instance of users relations so the previous one is not being changed then we can use
00:25:03.720 relational operations in order to create other relations so we have things like
00:25:09.390 join rename or streak project all this stuff is there and then we can simply access data so this is a really simple
00:25:17.340 concept you just have a set of tuples nothing else and a bunch of methods that you can use in order to manipulate the
00:25:23.250 data and access the data one of an interesting things one of the
00:25:29.970 interesting things is that you can actually do some crazy stuff like join two relations and then insert data into
00:25:35.760 those relations and axiom will actually distribute if we were you if you are
00:25:40.950 using an SQL database and you have two tables it will actually distribute the rights to the insert methods sorry
00:25:47.460 insert statements into separate tables so this is pretty cool and it's because
00:25:53.700 there is this concept of data independence in relational model and which says that it is a clear separation
00:25:59.220 that is enforced between the logical data and its physical representation so
00:26:05.610 this is pretty much what what Ruby object mapper is doing we have a logical
00:26:10.620 structure of our relations that we define in our application level and the
00:26:16.890 way it is actually stored in a database is something completely completely different handled by a separate layer
00:26:23.600 mmm Epsom handle handle handles that by
00:26:28.980 using adapters for databases so a really
00:26:35.390 huge concept that we're experimenting with is using relations
00:26:42.050 first class citizens it isn't she this is an interesting concept and what we
00:26:49.650 usually do these days in Ruby at least is that most of the over amps are using
00:26:55.410 active record pattern so like the the first class citizen in our in our system
00:27:00.600 is is a model right it is a class that gives us a curie interface so we have
00:27:06.570 this model and we run some Curie's to get the data and even though for example
00:27:12.510 here we have a scope called active so if we use the the Cure interface of active
00:27:18.870 record we do get a relation back although the relation is not the first class citizen you're in our system the
00:27:25.560 model is and the instance instances of this model also work as the first class
00:27:32.430 citizen in our system so the major
00:27:38.040 difference in philosophy here is that we would like to put relations in front and
00:27:44.100 when I say relations I simply mean the data right because relations is just
00:27:49.830 data so like the most basic implementation would be to have a
00:27:55.680 relation registry where internally we define relations that we need in order
00:28:01.350 to build other relations that we will expose publicly for our application so
00:28:06.420 with we don't think about running Curie's in our application we're thinking about the data we're thinking
00:28:11.490 about what data do we need and how it is being fetched from the database is just
00:28:16.920 completely completely separate concern so here we just create a relation registry and we have access to active
00:28:23.520 users and active users it's a relation that is the first class citizen in our
00:28:28.830 system and it's just data so the reason why this concept is at least should be
00:28:39.330 better is that we achieve better composability and better encapsulation and by composability I mean if we're
00:28:48.570 using relations and just relations we can combine them compose them to create
00:28:53.760 other relations and the order in which we are doing that is is just not important and not relying
00:29:01.210 on order is one of the things that we should do in order to reduce complexity and another thing is its encapsulation
00:29:08.110 when we are using relations we're talking about the data we're talking about what data we need we're not
00:29:13.540 talking about how we fetch the data so that's that's a huge difference so if we
00:29:21.610 take a look at a at an example where we want to find all the users without task
00:29:27.520 so we have users and they have task you might want to find all the users with no tasks so inactive record we would like
00:29:33.910 to use John but this won't work because this produces an inner join so what we
00:29:39.429 need to do is to just use an SQL a partial SQL and using a left outer join
00:29:45.929 yesterday we saw how we can do this with ariel with an object-oriented interface
00:29:52.350 but still we are talking about running and Kure here we are talking about details like what kind of a joint we
00:30:00.880 should use what kind of keys we are using in the on clause and all this
00:30:10.150 stuff that is just specific for a database and my experience is that when
00:30:15.730 i'm working on a bigger project where i have a lot of lot of color a lot of
00:30:24.720 methods that return puri object or
00:30:29.980 scopes we call them scopes I simply lose confidence pretty quickly I had many
00:30:36.370 times I had a situation where it turned out at some point that all the crazy chaining that we did in some place of
00:30:43.780 our system actually returns wrong data which sometimes it's not a big deal but sometimes it can be pretty huge bug
00:30:51.480 since we're exposing data that are for example that should be for example are
00:30:56.590 hidden so it's a big problem and when it
00:31:01.780 comes to relations as first class citizen the concept here is that we are not composing Curie's we're composing
00:31:07.030 relations and I know that it made sound it might sound a little bit confusing for you
00:31:12.620 since as I said active record curing methods return relations as well but we
00:31:18.620 are still thinking in terms of curious not in terms of relations and the difference is that when we combine
00:31:27.289 relations we use relational algebra to do that so we use relational operators
00:31:32.419 to do things and it is again it is like basic set theory we're just using basic
00:31:39.019 operations on on set that has some tuples and that's it so if you want to achieve the same thing find all the
00:31:45.169 users without task we're just using the difference operator or something that
00:31:50.179 even looks looks nicer just just uh Elias which is a minus so we say all the
00:31:55.549 users minus the ones with tasks which obviously gives us users without tasks and the trick here is that all the
00:32:04.399 relations if we are using an SQL database we can translate all the relations into an SQL query currently
00:32:14.440 the SQL generator in axiom can do pretty much everything although performance is
00:32:21.110 obviously a problem so we're not working on an optimizer that would make sure
00:32:27.169 that we are running a curious that are efficient so all those ideas we're
00:32:37.279 trying to incorporate them within this project called Ruby object mapper I mentioned it before it started started
00:32:45.139 as the second version of data mapper project but eventually we realized that it's just something completely new so we
00:32:51.830 decided to create a new project give it a new name and also initially we thought
00:32:57.200 that we're going to implement the data mapper pattern as described by Martin folder however recently we started
00:33:03.409 thinking about doing some things differently like using relations of the
00:33:08.750 first class citizen so the major focus in the project is is to focus on
00:33:14.509 relations which means to focus on just the data this is our primary
00:33:21.290 turn right now to create an interface that gives you access to the data which
00:33:27.530 is as simple as possible so that working with the data is just trivial and we
00:33:34.610 also want to want to really achieve clear separation between the database structure and your logical structure
00:33:41.870 that you have in your system and another big part of Ruby object mapper is
00:33:47.440 mapping to objects which is like the core one of the core parts of the data
00:33:52.820 mapper pattern so we have data in the database and then you want to map the data to some objects so initially we
00:33:59.360 thought that this is a huge thing in the project but to be honest right now we're
00:34:05.660 thinking that yes sometimes we might want to map things to something more sophisticated but in many cases we can
00:34:12.620 just use the data tuples and that's it so the next part is is just simplicity
00:34:19.100 we're trying to we're trying to narrow down the interfaces as much as possible we want to have just one way of doing
00:34:26.660 things which is a little bit against the Ruby philosophy but we just disagree
00:34:32.750 with that so we're trying to have for example for all things like creating
00:34:39.919 data we just want to have one interface we don't want to introduce many
00:34:45.320 interfaces just because we want to have some optimism ization for for a database
00:34:50.390 right like an active record you have methods like update attribute update
00:34:56.450 attributes and other things that that are there just because you sometimes want to you want to use them because of
00:35:02.450 performance right so we're trying to avoid that and we're trying to move the optimization to a separate layer where
00:35:10.270 an efficient cube SQL query will be generated and so when it comes to
00:35:17.960 defining logical schema in Ruby object mapper this is pretty much a DSL on top
00:35:24.230 of axiom which is which is also following the philosophy where we're
00:35:30.860 focusing on building small tools that are then used I some higher-level tools that are just
00:35:36.660 a simple wrappers that simply expose a DSL that is convenient right however
00:35:44.430 Rome itself is pretty that simple internally so in Rome you can define
00:35:51.300 relations in a pretty pretty similar way as you do with axiom and one of the
00:35:57.720 ideas that we have right now is to have ability to define to define which relations will be private which means
00:36:04.410 that they won't be accessible within your app they are only there in order to
00:36:10.290 create other relations that you will expose for your app which we believe
00:36:17.460 should should give better encapsulation so if you want to define external
00:36:26.190 external relations or public relations you can just define them and like that
00:36:33.210 without passing the internal true argument and you have access to all the
00:36:39.690 relations that you define before and you can just combine them however you want using relational algebra operators and
00:36:46.950 then Rome will simply expose everything that you defined so in your app you only
00:36:53.160 creating Curie's you won't be writing things that are tightly coupled to the structure of your database you will be
00:36:59.160 simply accessing the data and important part here is that relations should be
00:37:04.290 context-aware which means that here we have users task relation which returns
00:37:11.310 all the task for a particular user so our context here is that we need the
00:37:17.400 user ID so this is one of the requirements and it will work like that
00:37:24.420 so you will simply pass in the user ID and you will get the data back so this
00:37:29.610 is what we and this is this is the major difference because what we usually do is that this part here in inside this blog
00:37:37.350 this is this is what we would usually right inside our application right like in the controller or somewhere else
00:37:43.500 right it's it's available so we do that even though like the best practice is to
00:37:49.240 your scopes etc but the truth is if something is available then you're going to use it right because it's just you
00:37:55.600 know it's simple it's conveniently we're going to just write it without thinking too much about it so this is like the
00:38:02.619 major difference here um so the the next big part is is mapping data to object
00:38:07.930 but as I said we're kind of changing our minds and and right now we're thinking
00:38:13.420 that mapping is not such a big such an important feature but it can be helpful
00:38:20.500 it can be just handy so we have we have something like a mapping which is a way
00:38:28.210 of defining how you want to map relations to some other objects so Rome
00:38:34.090 will create entity classes for you and it will it will just create a way of
00:38:42.570 instantiating those those entity classes using the data from from relations so
00:38:48.940 this is an example of a basic attribute mapping so it would generate it would
00:38:54.640 generate a task entity and it will it will return entities like instances of
00:39:02.109 this entity class by using the attributes right we also support
00:39:08.020 something like using embedded values so you will be able to create aggregates so
00:39:15.280 here we would have a task entity that has a title and it also has a user
00:39:20.859 instance and it will like automatically generate those classes for you and and
00:39:28.260 yeah because what ya one thing that I forgot to mention is that you in data
00:39:36.310 mapper pattern you can't really have like dynamic things so in active record you do things like user first and then I
00:39:43.450 don't know dot tasks right here you you have to define it up front because once
00:39:49.060 you start accessing the data it already needs to know what will be instantiated and once it's it's nan Chi ated it
00:39:55.240 doesn't have access to persistence layer because it's separated so that's like a major difference between active
00:40:00.549 datamapper approach yeah so the last part is just simplicity even though like
00:40:07.359 the whole Rome project is it is complicated because it's it's it's a lot
00:40:12.999 of different problems however we're trying to solve them using separate libraries so we have axiom we have we
00:40:19.179 have optimizer we have more for for mapping all this stuff is there so that
00:40:25.239 ROM will simply use those tools and just expose the dsl on top of those tools so
00:40:32.709 the focus is on simplicity even though we have many many libraries involved we
00:40:38.109 are still trying to achieve a very consistent interface so that it will be
00:40:44.469 just simple to use so to wrap this up
00:40:49.529 Rome will give you a way of accessing the data you won't be thinking in terms
00:40:54.849 of relationships re in terms of Curie's you won't be thinking about your database columns whatever you will be
00:41:00.969 just accessing relations and you will define those relations inside your logical schema definition it will give
00:41:07.420 you a simple way of mapping the data to some other objects if you want that however we think that in many cases you
00:41:15.400 will be happy with just the data we will also want to have a simple interface for
00:41:21.609 inserting data so there's no point in creating I don't know a user instance in
00:41:28.719 order to do to to save its data using data hash is all you need and we also
00:41:35.019 want to support something like using the relations that you defined to manipulate
00:41:40.359 them so you can for example join many relations as a context for for a
00:41:49.209 persisting a nested data structure and the system will distribute the individual operations due to two
00:41:55.719 separate tables for you yeah so embrace
00:42:01.509 simplicity and convenience can come later you can always look at things later and and see how we can simplify
00:42:08.199 stuff from the point of view of a user that this is using your interfaces
00:42:14.350 I i don't think that focusing on convenience so much right from the start is a good strategy yeah and that's it
00:42:21.940 thank you
00:42:30.549 thanks Peter any questions for him so
00:42:38.329 one question I've been walking around and asking different companies and
00:42:43.730 developers about how far they go with this with approach you describe and most
00:42:51.650 of you of them are pretty happy with a detective records and they are maybe
00:42:57.230 using additional use cases layer but for all the staff they are happy and do you
00:43:04.069 have examples and maybe you have your own experience when you should go that
00:43:09.530 far with operational concerns when you develop a bail application I haven't
00:43:18.799 written any application which would fully be based on those concepts I'm
00:43:26.000 using some of those concepts in some places in my applications and really happy with those Martin one of the guys
00:43:33.980 from from the team is right now working on an application where he's using all this stuff he implemented most of it
00:43:41.780 already in a separate project we're now collaborating together to get all this
00:43:47.569 stuff into Ruby object mapper and he's extremely happy with this approach he's
00:43:55.220 been working on this this application for a few months already it's a lot of code already and he's really confident
00:44:02.750 that this approach really leads to Tuesday to just simplicity but yeah as
00:44:09.890 you said many people are happy with active record many people are happy with the way Reyes works I'm not questioning
00:44:15.230 that race word for me in a lot of cases I'm still happy using rails something
00:44:22.730 that I recently started doing was that I switched to sequel without using its
00:44:29.569 model layer I'm just using its security interface and I'm doing something like I
00:44:35.930 showed you in the slides and I found it to be really great I'm just focusing on
00:44:43.050 on the essential stuff and not I'm just rejecting everything else it feels good
00:44:48.180 but it's it's it's more work it's just more work because I need to write more code but still sometimes it makes sense
00:44:55.620 sometimes it doesn't arise depending on your context but overall I'm pretty confident that if your system is growing
00:45:03.060 then eventually you will appreciate an approach where you're just focusing on simplicity and less inconvenience okay
00:45:10.410 thank you do you think it makes more sense when you startin to write a new
00:45:16.890 application to start with your approach or it's okay to start with regular old
00:45:22.500 regular rails way and then trying to switch trying to refactor I think that
00:45:31.670 depends right if you're working on your own product and you got like better
00:45:38.580 funding than you know then you can do whatever you want and it will probably be great but usually you don't have the
00:45:46.380 situation so right now I would just leverage the power of the tools that I have and then worry about things later
00:45:54.830 Yeah Yeah right now we just don't have the tools that I described today they
00:46:02.400 are not as mature as as Reyes and its ecosystem it's just not there yet and it's going to take years to get there so
00:46:09.420 yeah it's pretty pretty much an experimental stuff so building things on top of experimental software is
00:46:15.600 obviously pricey so yeah okay thank you the last question about the dimension
00:46:21.810 okay try to use it in while you develop and then turn it off
00:46:28.950 when you publish the game Jim or no now
00:46:35.400 I haven't in some of my projects I I
00:46:40.589 just use it and nobody complained but I know that Marcus another guy from the
00:46:47.070 team he had that use case he use adamantium in his project and then he
00:46:52.380 had to turn it off because it was too slow so the slowness you told ballsy it
00:47:00.599 is gonna turn it off yeah yeah okay
00:47:05.730 because you're not freezing everything deeply um just a quick question how do
00:47:15.570 you handle validations like if you're just in general with this scheme yeah
00:47:21.720 I'm having something like a validator object i'm currently i'm just using the
00:47:30.510 active model staff because that's that's the most powerful thing that exists right now one of one of the team members
00:47:39.260 are war I think he's still working on a
00:47:45.540 library called Vanguard which is like a library dedicated for validations that
00:47:52.710 is completely like separated from from everything but there are still some some
00:47:57.720 interesting problems to solve like like you know if your validation procedure
00:48:02.760 requires the database connection and what do you do and things like that but your engineer in general on trying to
00:48:09.599 use the database constraints for for certain things and rely on that you're
00:48:15.119 right now Martin is using the other guy right now he's using an approach where
00:48:22.410 he's just relying on constraints and catching errors from the driver if something wasn't fetched a story wasn't
00:48:28.910 saved he's just fetching error error and producing an error message he's doing
00:48:35.670 that right now and he's still not super confident about like the implementation details but in general
00:48:42.570 like moving towards a different direction where it should work for him
00:48:47.790 pretty well yeah since we're talking
00:48:54.420 about implementing an active model stuff are you mostly using this to generate
00:49:00.750 sequel query statements are you doing any like serializable stuff like JSON or
00:49:06.180 anything with it with what with sequel you're just like generating sequels queries are like statements are you
00:49:12.840 doing anything with like JSON or anything like that but uh no I'm just using it for generating Curie's yeah all
00:49:20.640 right thanks Peter if you guys have any questions after that can look for him
00:49:26.040 because we're running a little bit short on time Thanks thank you
00:49:35.660 you
Explore all talks recorded at Red Dot Ruby Conference 2014
+20