Thank you Josh, for sharing your perspective :). Always helpful for me to learn new approach even If i feel uncomfortable about it at the moment. This is how I can achieve growth in the future.
Very good video, thank you! 2:36 is how i felt when i re-builded 2 projects with reactive programming, things just got so much simpler! Follow the flow!
This is a great explanation! I stumbled into this style at work roughly the same way as the example. As the application grew and the complexity with it, it became increasingly harder to handle information through the application. Even small changes could have cascading rewrites. The way to for me now it just hold apis declaratively. Use tap at the component for any information needed and just let the rest be handled by the async pipe. The way I look at this now is a balance between the two. Declarative code requires more setup so to speak but the more that setup is used the more it pays for itself down the road.
your explanaitions are always on point which makes it easy to get the bigger picture or the idea behind it thank you very much 👍 you would be a great teacher ✌
I absolutley agree with you. I think the mix of booth is the way to go as long as the dev (or dev team) is okay with that and everyone on the project can handle AND understand the codebase.
already have an itch to refactor that action property to a discriminated union or enum type :D Thanks for the vid and your work. Love functional programming. ❤ Your vids made me look back at my code and make it more reactive.
Id also love to see this. I tried to do a bit of experimenting around this myself as I was learning how to do declarative, but the calls to .next() were the closest I could come up with.
I've been thinking about this a lot lately, very good nuanced video on the advantages! I've also noticed another area where the imperative vs declarative has impacted me: CSS is usually very hard for devs, even though it's declarative. It's sometimes a lot easier and stable to do something with JS. I'm not sure what to attribute that too though, maybe it's just because CSS has had feature after feature after feature and isn't a well thought through declarative language from the get go. I enjoy SQL a lot on the other hand, the abstractions of WHAT from the the HOW is just beautiful there.
Very good explanation. I think that using an example with the scan was not the best idea. Feels like the first I saw a reduce haha. Most of the time Declarative code very easy to read. But yeah it's the kind of things that you can only fully appreciate once you've committed to it
Definite "like". Nicely presented. Would love to see one that's not Angular related. As for imperative vs declarative... I'm the sort of Dev that doesn't like abstractions or static sugar so no declarative for me (ok just a sprinkling). As you stated, declarative gets reduced to imperative anyway. This reminds me of the ORM vs SQL or DOM vs framework wars.
Nice explanation! Ive been reading about this alot and this was the only example that made me understand it. Ive always been a declarative type of programmer since as an android dev, ive started with java. Now after transitioning to kotlin ive been trying functional. So now i basically do a bit of both 😅, but i try to avoid those vertical trains of functions.
In the declarative example: Why does the "Update Data to API" stream go via the employee component and not is not directly triggered by the service? 3:15
Watching your videos about declarative vs. imperative, I definitely can see the benefits of going more declarative. I think my biggest problem with this is the naming of the methods. Like what does "next" mean? Of course we can learn and memorize what these RxJs methods mean, but method names should intuitively describe what's happening. Things like "addEmployee" for example. We just need some sort of renaming or abstraction around these method names so that you can look at a method and intuitively understand what it's purpose is, instead of having to memorize it. It just feels like the names of these operators make things harder than they have to be.
This isn't specifically related to declarative code itself, more so to RxJS which just so happens to be a way in this context to write declarative code - in an Angular context you would sort of need to learn RxJS well in order to create declarative code, and so would pick up on these meanings as you go (e.g. "next" is a way to emit the "next" value on a "subject" - another concept which is non obvious but is part of learning how to use RxJS). I do agree that much of this stuff is very much non intuitive.
I am one of those who commented on that previous video that I would 100% of times prefer the imperative example and for that example I still think so. I guess most people use declarative code in an amount they feel comfortable with.
It's like you say, some levels of complexity in components logics push us to organise better, in a more effective and error prone way. The step is sometimes high but it's worth it. Thanks anyway for the great content.
Love your content, especially because you really see both sides, that alone is awesome in "the land of extremists" that is todays dev-community. Everyone praising async pipe without telling you downsides like initial null-values, multiple-subscriptions, and so - it's a plague! For me personally readability is still the most important thing by far and the declarative side took me just too far long to fully comprehend. So in my book that makes the right side (in this example) better, because it is was I value the most. I agree with that imperative code can get messy, but honestly: so will the declarative part. When you open a file and need 10 minutes to understand the 2 monstrous "elegant expressions" that's also not great. Also in Angular there are also A LOT of pitfalls, like double subscriptions and subscription leaks and you can fuck things up much easier.
This was interesting to watch, because from my point of view declarative code is much more readable tha imperative (I almost don't understand imperative approach if I'm not spending a couple of minutes to understand, while declarative I understand it the moment I read the lines, because eveything is organised in 'containers'). Seeing that may not be the case for everyone is interesting.
Thank you for not being opiniated and for being honest about the pros and cons of each style. Nice diagrams, they make it very clear why declarative style is our ally in the long term.
Can I ask what software you used to draw the diagrams? I am writing a programming article and I would like to add a couple of diagrams to explain the relationship between different classes. As always, nice video and thanks for sharing you point of view Josh. I also prefer using a mix of declarative and imperative, specially for cases where trying to remove the last 10% of imperative code results in having to rely on wacky approaches or results in much more complex code.
Technically your assessment is spot on, and your diagrams illustrate it well. In professional practice, however, there is the human factor, too. You may work mostly declaratively, but fellow devs may encounter at least 2 big problems. 1. Being so unfamiliar with declarative syntax that it drains their energy before they get to learn it for the task at hand. 2. Being so incapable of assessing how the cognitive load of working with code affects them, that they don't see your point about the long-term / large-scale benefits. They may therefore always prefer their familiar, momentarily easier, imperative way way. In the end, in a business, this translates to losses unless there is some extra budget to give the devs 1. time to learn and 2. education on what efficient work and optimized cognitive load actually means, in practice, for themselves.
Yes - switching to a declarative style requires the entire team to be on board, and if required the investment to learn it. Anything else is a recipe for disaster that would be something like half the team using state management library X and the other half state management library Y.
I have the same take as you at the end with OOP vs Functional you dont want to go all out extreme, but favour one style with sprinkles of the other, for me thats functional first but oop where it makes sense/feels convenient.
I generally do a mix of the two, but avoid things like tap since it is not a common thing in other languages and I can not understand it without thinking for a bit.
It is not that it is bad, but can you explain it in five words or less. Would someone senior or junior (that does not know of RSJX) be able to understand it in less than five mins?
I've been sitting on a declarative framework for UX/UI which similarly "declares" all possible interface states of an application in a global "experience architecture" map. I wonder if that can be "hooked up" to sync with an application's software architecture (or at least generate scaffolding) 🤔
Thank you for your fantastic explanations but it's still not clear to me for instance how to log in without manually subscribing? Can you give an example of this? Thanks.
For login scenarios I would use an effect with NgRx Component Store - technically you can say this also is not "fully declarative" as behind the scenes Component Store just subscribes to the observable for you and then you can get the value which you imperatively set in the stores state, and then from that point things are back to being "reactive/declarative" because the part your application will react to is the stream of changes coming out of the store (e.g. for your loggedInUser$ selector or whatever). So it's kind of like a convenient little imperative black box that allows you to keep the overall declarative structure of the app. I've never really tried going a declarative approach without something like Component Store for this use case.
I was thrown on angular and RxJS without preparation and... really like RxJS in practical use! I read about it few years ago but then seemed fancy academic gun to hit nails but now i changed my mind.
but, this assumes the developer knows or can find the other functions like you used, pipe, .... AND understand how they work and how u can construct with them. none of my dev environments show available methods with decent descriptions
Yes this is the hard thing about adopting declarative code in Angular - you need to spend time learning RxJS, and that isn't easy. It's worth the investment imo, but it is an investment.
@@JoshuaMorony but it's not just rxjs, it's every stinking lib/function you call. I'm not a professional developer, but I write code everyday on multiple different platforms, w different IDEs, none of them help me even KNOW what methods are available. and some don't support declarative
Imperative is how you start coding an app, and declarative is how you end up breaking down complex imperative code into small imperative blocks of code. This's just about applying good programming practises. However, it's wrong to say that imperative code is typically that messy as you show in the right side, that's simply not true, unless you're a bad programmer.
3:15 i don't get why you compare normal code vs RxJS or Observables? - RxJS for me look is a Fluent API on C# where you can chain operations. Declarative vs Imperative / OOP vs FP ... and many more thing can't live without mixing them.
Thanks josh. I have tried to implement this code. But the problem is, in sideeffect, u r making a single api call for evey action which is accepting array of employees. But in general we have different api methods for each action (crud). How to call those http service, based on individual crud action. I m trying to figure it out ,but not getting it. Does Anyone have any idea?
Does the pattern in this video suit you: ruclips.net/video/44_IcGPKQ_M/видео.html - this is easier to reason about, you could have an add$ source, edit$ source, delete$ source and each can be handled individually
@@JoshuaMorony thanks, i will check this out. I m trying to learn these things, and watching your videos. Its easy to revisit because they are short and precise. Concepts you are advocating are fascinating. I m not questioning on patterns you advocate doesn't work in real world. They are perfectly fine. Everyone have different scenarios and to fit your patterns in their scenarios can be challenging sometimes. But in the end your patterns always works.
it's interesting how you write all of the subject that way using scan... not readable at all, but great code... I would just keep the add remove functions separate in the service with next like your 2nd example... much cleaner, although would be interesting to see speed differences
Another hard thing about covering this topic - I often do prefer to just next streams with values, but that's an imperative approach. It does still mix in well with an overall declarative approach, but the scan approach is more declarative so it seemed a better/fairer option to me to highlight as the declarative approach.
It's fine to break things up like this - it's still clear from looking at the declaration of the thing using the pipe that it sues that pipe, and the pipe is defined upfront/doesn't change. It's reassignments that are the problem (e.g. at one point of time thing X = Y but later it is reassigned such that thing X = Z and that change is not defined in the declaration itself)
This might sound a bit extreme but in my experience there are 2 types of developers, The ones who get RxJs and the ones who don't! and the ones who get RxJs won't write a single line of imperative code event if you point a gun to their heads :))
I think one major benefit of Declarative code is, how easy it is to make changes. Clients can be fickle and might want you to change how a component works. With declarative code, it is so easy to make changes because all logic is contained in a box. Eg: Load employees only when the event from child component is fired and there is at least 1 filter setup and input parameter is set to true. With imperative code, this means tons of if's and else's and multiple areas calling the loadEmployees function. With declarative code, this is just combineLatest. Latter is much more open to modifying the logic with minimal bug risk.
For some people code can be seen as imperative, while for others it's declarative. It's the same debate as "too little abstraction for some people, while for others it's abstracted enough already or even too much" For me personally - the example you've presented with signals is actually declarative enough, because you're not manually updating value in every single place you need to update it but rather have some function that listens on given value change or some other action, to automatically perform some effect. And that's my sweet spot My biggest problem is that a lot of Angular devs say that in order to write code declaratively, you have to use RxJS... which actually adds a lot of complexity, because it shrinks and hides a lot processes into small... weirdly named function calls which you need to learn, rather than just simply declaring your reactive value and declaring how it should be updated
Definitely don't want to enforce any dogmatism around how declarative code should be written, I like the idea of doing whatever works best for you/your team and evaluating that over time. By my definition of declarative (which seems to line up reasonably well with yours, i.e. "declare a value and how it is updated over time") I am one of those who thinks you do need RxJS (or something else) to code declaratively in Angular. It will be a bit better now with signals because you can do some declarative stuff out of the box, but as soon as you start touching async stuff you would need RxJS if you wanted to keep things declarative in the sense that you can understand what something is just by looking at its declaration. RxJS handles the "how it is updated over time" part for asynchronous events, otherwise things need to be set imperatively when some async process finishes.
People don't know how bad their imperative codebase really is until they switch to working in a declarative codebase. A mature imperatively designed codebase is a huge headache to troubleshoot. Having your functionality encapsulated frees up a lot of mental bandwidth that gets spent trying to find and remember all of the different places where something gets updated.
True. It's like JS vs TS. Yes, its harder to go with types but it gives you more time to think about you want to accomplish rather than trying not to break something because you chose wrong value
I don't get this diagrams. "Understanding how things change" unless function that sets myValue is not using global variables. You can easily reason what would be myValue = fn( a, b, c ) as it depends on arguments. Code looks more like this fn( ... ) { fn1; fn2; fn3; } it's almost exactly the same as left side where you have show as encapsulated code. Both example look bad, structure, naming. Overall code composition and architecture is dumb. Why you have to load employees to add or remove one. This is biggest problem in software accidental complexity that create this whole clusterfuck code.
When you say you do it because “it is easier”, that is not a fact it is an opinion. If a person prefers declarative then it will be easier and they will enjoy coding it more, which is a positive for them, but the same goes for someone who prefers imperative. It’s really mostly about personal preference. To be a good engineer I believe you need experience with both so that you can understand both types of code and can work productively in teams that use either or both approaches.
Sure, but my point is (at least I think it is, it's been a while since I've seen this video) that people are coming to an opinion on imperative vs declarative code without really understanding what declarative code is or the benefits it might bring. People often dismiss declarative code entirely because it just looks more complicated, so I'm highlighting the point that I do it because it is the easier option given the bigger picture (and yes, we can tack a "easier, for me" on there) And I don't really think it falls under personal preference, I think the ramifications of one approach or the other are quite significant (versus say how you like to name your variables) - technically still a preference I guess, but to me that would be like labelling all of software architecture concerns as personal preferences
11 месяцев назад
Your declarative code is not declarative, it's declarative/functional at best. You are still describing how to get to your result as opposed to just describing what your result should be. HTML, Prolog, and SQL are example of declarative programming. More functional javascript (which it should be anyway given JS is just Lisp disguised with a C-like syntax) is far from being declarative.
I think being imperative at the "extremities" of your apps reactive graph is not a big deal (and can be easier), so way up where data first flows in, or at the very end where data is flowing out. Imperative in the middle makes a mess.
@@ajayraja6636 I don't really know how people are writing React and Solid apps, but generally you are able to write both declarative and imperative code within the same framework. The imperative example I gave is imperative because 'employees' is set after its declaration, whereas with the declarative example 'employees$' is fully defined at the time of declaration.
@@ajayraja6636 yeah React and SolidJS are still somewhat imperative. They're reactive only after state is set. For a 100% reactive example check out CycleJS
@@JoshuaMorony I can't fully explain here due to RUclips Comments Limitations. Therefore I provided a Github Gist where I explain it. Here the link gist.github.com/AjayTheWizard/248a6fabed3389a2b0d81370dcdc6bf8
Months ago you convinced me to build an app with reactive declarative code. I just finished a proof of concept and I have a couple of thoughts/tips which you and your subscribers might find useful :) - It was not easy to change my mental modal, but I am happy that I did! - Especially in the beginning what you can do, is to write the code imperatively and ask ChatGPT to refactor it in a "reactive declarative" way. - Since it is not a perfectly defined and popular concept, it is helpful to give ChatGPT one or two examples. Also you might need a bit of a back and forth, to make it work in a way as Joshua does. - ADD COMMENTS!! This will help you understand your code much better, especially on the next day or day after. Also it helps to learn the concepts and helps other developers to understand it. - Once you've done this a couple of times, you'll have a better understanding, e.g. what kind of operators to use when. - You have to understand that you can make anything a stream, e.g. 1) getting data and showing it as a list 2) filtering the list and only showing the filtered results 3) deleting a list item and updating the list ... and combine those streams into one observable to which you can subscribe via an async pipe! 4) Sometimes it might feel like an overload, but once you get the concepts you will appreciate your own code much more. I only have two mid-level concerns: 1. Testing - I'm not sure how well it works to test components, especially those which have multiple streams 2. Newcomers - it's definitely harder for people who are not familiar with this coding style, but if you add comments and the people can use ChatGPT I think it is not doable and worthwile. @Joshua I'd love to hear your thoughts, especially in regards to testing! (Cypress)
Thanks for sharing your experience, very interesting! As for testing I've got a few videos on my channel around the topic (one specifically focuses on the idea whether reactive code is harder to test), but in general I've never really faced anything annoying (probably mostly because I use observer-spy for just about everything)
Join my mailing list for more exclusive content and access to the archive of my private tips of the week: mobirony.ck.page/4a331b9076
Thank you Josh, for sharing your perspective :). Always helpful for me to learn new approach even If i feel uncomfortable about it at the moment. This is how I can achieve growth in the future.
Very good video, thank you! 2:36 is how i felt when i re-builded 2 projects with reactive programming, things just got so much simpler! Follow the flow!
This is a great explanation! I stumbled into this style at work roughly the same way as the example. As the application grew and the complexity with it, it became increasingly harder to handle information through the application. Even small changes could have cascading rewrites. The way to for me now it just hold apis declaratively. Use tap at the component for any information needed and just let the rest be handled by the async pipe.
The way I look at this now is a balance between the two. Declarative code requires more setup so to speak but the more that setup is used the more it pays for itself down the road.
your explanaitions are always on point which makes it easy to get the bigger picture or the idea behind it
thank you very much 👍 you would be a great teacher ✌
I absolutley agree with you. I think the mix of booth is the way to go as long as the dev (or dev team) is okay with that and everyone on the project can handle AND understand the codebase.
already have an itch to refactor that action property to a discriminated union or enum type :D Thanks for the vid and your work. Love functional programming. ❤ Your vids made me look back at my code and make it more reactive.
Now I wanna see how you would have to do it if you wanted to go full declarative 😮.
Great video as always!
Id also love to see this. I tried to do a bit of experimenting around this myself as I was learning how to do declarative, but the calls to .next() were the closest I could come up with.
I think this would make a fun video
I've been thinking about this a lot lately, very good nuanced video on the advantages! I've also noticed another area where the imperative vs declarative has impacted me: CSS is usually very hard for devs, even though it's declarative. It's sometimes a lot easier and stable to do something with JS. I'm not sure what to attribute that too though, maybe it's just because CSS has had feature after feature after feature and isn't a well thought through declarative language from the get go. I enjoy SQL a lot on the other hand, the abstractions of WHAT from the the HOW is just beautiful there.
Very good explanation. I think that using an example with the scan was not the best idea. Feels like the first I saw a reduce haha. Most of the time Declarative code very easy to read. But yeah it's the kind of things that you can only fully appreciate once you've committed to it
Definite "like". Nicely presented. Would love to see one that's not Angular related. As for imperative vs declarative... I'm the sort of Dev that doesn't like abstractions or static sugar so no declarative for me (ok just a sprinkling). As you stated, declarative gets reduced to imperative anyway. This reminds me of the ORM vs SQL or DOM vs framework wars.
Nice explanation! Ive been reading about this alot and this was the only example that made me understand it. Ive always been a declarative type of programmer since as an android dev, ive started with java. Now after transitioning to kotlin ive been trying functional. So now i basically do a bit of both 😅, but i try to avoid those vertical trains of functions.
In the declarative example: Why does the "Update Data to API" stream go via the employee component and not is not directly triggered by the service? 3:15
It doesn't have to - I was modelling the code shown at 1:25 specifically but you could probably refactor this and move some stuff up to the service
Watching your videos about declarative vs. imperative, I definitely can see the benefits of going more declarative. I think my biggest problem with this is the naming of the methods. Like what does "next" mean? Of course we can learn and memorize what these RxJs methods mean, but method names should intuitively describe what's happening. Things like "addEmployee" for example. We just need some sort of renaming or abstraction around these method names so that you can look at a method and intuitively understand what it's purpose is, instead of having to memorize it. It just feels like the names of these operators make things harder than they have to be.
This isn't specifically related to declarative code itself, more so to RxJS which just so happens to be a way in this context to write declarative code - in an Angular context you would sort of need to learn RxJS well in order to create declarative code, and so would pick up on these meanings as you go (e.g. "next" is a way to emit the "next" value on a "subject" - another concept which is non obvious but is part of learning how to use RxJS). I do agree that much of this stuff is very much non intuitive.
I am one of those who commented on that previous video that I would 100% of times prefer the imperative example and for that example I still think so. I guess most people use declarative code in an amount they feel comfortable with.
It's like you say, some levels of complexity in components logics push us to organise better, in a more effective and error prone way. The step is sometimes high but it's worth it. Thanks anyway for the great content.
Love your content, especially because you really see both sides, that alone is awesome in "the land of extremists" that is todays dev-community. Everyone praising async pipe without telling you downsides like initial null-values, multiple-subscriptions, and so - it's a plague!
For me personally readability is still the most important thing by far and the declarative side took me just too far long to fully comprehend. So in my book that makes the right side (in this example) better, because it is was I value the most. I agree with that imperative code can get messy, but honestly: so will the declarative part. When you open a file and need 10 minutes to understand the 2 monstrous "elegant expressions" that's also not great. Also in Angular there are also A LOT of pitfalls, like double subscriptions and subscription leaks and you can fuck things up much easier.
This was interesting to watch, because from my point of view declarative code is much more readable tha imperative (I almost don't understand imperative approach if I'm not spending a couple of minutes to understand, while declarative I understand it the moment I read the lines, because eveything is organised in 'containers'). Seeing that may not be the case for everyone is interesting.
Thank you for not being opiniated and for being honest about the pros and cons of each style.
Nice diagrams, they make it very clear why declarative style is our ally in the long term.
Thanks for this come back on declarative code ;)
Can I ask what software you used to draw the diagrams? I am writing a programming article and I would like to add a couple of diagrams to explain the relationship between different classes.
As always, nice video and thanks for sharing you point of view Josh. I also prefer using a mix of declarative and imperative, specially for cases where trying to remove the last 10% of imperative code results in having to rely on wacky approaches or results in much more complex code.
Sure I use Excalidraw for most of my diagrams
Technically your assessment is spot on, and your diagrams illustrate it well. In professional practice, however, there is the human factor, too. You may work mostly declaratively, but fellow devs may encounter at least 2 big problems. 1. Being so unfamiliar with declarative syntax that it drains their energy before they get to learn it for the task at hand. 2. Being so incapable of assessing how the cognitive load of working with code affects them, that they don't see your point about the long-term / large-scale benefits. They may therefore always prefer their familiar, momentarily easier, imperative way way. In the end, in a business, this translates to losses unless there is some extra budget to give the devs 1. time to learn and 2. education on what efficient work and optimized cognitive load actually means, in practice, for themselves.
Yes - switching to a declarative style requires the entire team to be on board, and if required the investment to learn it. Anything else is a recipe for disaster that would be something like half the team using state management library X and the other half state management library Y.
I have the same take as you at the end with OOP vs Functional you dont want to go all out extreme, but favour one style with sprinkles of the other, for me thats functional first but oop where it makes sense/feels convenient.
Can you show the fully declarative counter example for 4:17?
I don't have an example on hand, though a "going fully declarative" style video would probably be interesting to make
@@JoshuaMorony Sure. Especially focusing on events from many source. For example polling on interval basis, and also on user request.
@@JoshuaMorony You’re just talking about getting a ref to the button and then creating an observable from the click event, right?
@@michaelurban856 yes - we would try to compose things from the click events directly rather than triggering something manually with a handler
@@JoshuaMorony Yeah, nothing too unusual there.
I generally do a mix of the two, but avoid things like tap since it is not a common thing in other languages and I can not understand it without thinking for a bit.
Tap is not that bad.. depending on your side effects, of course :)
It is not that it is bad, but can you explain it in five words or less. Would someone senior or junior (that does not know of RSJX) be able to understand it in less than five mins?
I've been sitting on a declarative framework for UX/UI which similarly "declares" all possible interface states of an application in a global "experience architecture" map. I wonder if that can be "hooked up" to sync with an application's software architecture (or at least generate scaffolding) 🤔
Thank you for your fantastic explanations but it's still not clear to me for instance how to log in without manually subscribing? Can you give an example of this? Thanks.
For login scenarios I would use an effect with NgRx Component Store - technically you can say this also is not "fully declarative" as behind the scenes Component Store just subscribes to the observable for you and then you can get the value which you imperatively set in the stores state, and then from that point things are back to being "reactive/declarative" because the part your application will react to is the stream of changes coming out of the store (e.g. for your loggedInUser$ selector or whatever). So it's kind of like a convenient little imperative black box that allows you to keep the overall declarative structure of the app. I've never really tried going a declarative approach without something like Component Store for this use case.
I was thrown on angular and RxJS without preparation and... really like RxJS in practical use! I read about it few years ago but then seemed fancy academic gun to hit nails but now i changed my mind.
Nice diagrams! Can you say what service/application did you use for them?
Thanks I use Excalidraw
but, this assumes the developer knows or can find the other functions like you used, pipe, .... AND understand how they work and how u can construct with them.
none of my dev environments show available methods with decent descriptions
Yes this is the hard thing about adopting declarative code in Angular - you need to spend time learning RxJS, and that isn't easy. It's worth the investment imo, but it is an investment.
@@JoshuaMorony but it's not just rxjs, it's every stinking lib/function you call. I'm not a professional developer, but I write code everyday on multiple different platforms, w different IDEs, none of them help me even KNOW what methods are available. and some don't support declarative
Imperative is how you start coding an app, and declarative is how you end up breaking down complex imperative code into small imperative blocks of code. This's just about applying good programming practises. However, it's wrong to say that imperative code is typically that messy as you show in the right side, that's simply not true, unless you're a bad programmer.
Neat video Josh. What tool do you use for these nice conceptual component visualizations?
I use excalidraw for most of my diagrams
Once I got into RxJS and it's integration with libs like NgRx, I would never go back to useEffects or some react sagas again 🙏🏻
3:15 i don't get why you compare normal code vs RxJS or Observables? - RxJS for me look is a Fluent API on C# where you can chain operations.
Declarative vs Imperative / OOP vs FP ... and many more thing can't live without mixing them.
exactly my point too. Rxjs is declarative, but declarative is not rxjs
Thanks josh.
I have tried to implement this code.
But the problem is, in sideeffect, u r making a single api call for evey action which is accepting array of employees.
But in general we have different api methods for each action (crud).
How to call those http service, based on individual crud action.
I m trying to figure it out ,but not getting it. Does Anyone have any idea?
Does the pattern in this video suit you: ruclips.net/video/44_IcGPKQ_M/видео.html - this is easier to reason about, you could have an add$ source, edit$ source, delete$ source and each can be handled individually
@@JoshuaMorony thanks, i will check this out.
I m trying to learn these things, and watching your videos. Its easy to revisit because they are short and precise.
Concepts you are advocating are fascinating.
I m not questioning on patterns you advocate doesn't work in real world. They are perfectly fine.
Everyone have different scenarios and to fit your patterns in their scenarios can be challenging sometimes.
But in the end your patterns always works.
it's interesting how you write all of the subject that way using scan... not readable at all, but great code... I would just keep the add remove functions separate in the service with next like your 2nd example... much cleaner, although would be interesting to see speed differences
Another hard thing about covering this topic - I often do prefer to just next streams with values, but that's an imperative approach. It does still mix in well with an overall declarative approach, but the scan approach is more declarative so it seemed a better/fairer option to me to highlight as the declarative approach.
If I declare pipes in separate function (my_pipe = pipe()) and use them in main declaration. Is it still declarative approach?
It's fine to break things up like this - it's still clear from looking at the declaration of the thing using the pipe that it sues that pipe, and the pipe is defined upfront/doesn't change. It's reassignments that are the problem (e.g. at one point of time thing X = Y but later it is reassigned such that thing X = Z and that change is not defined in the declaration itself)
This might sound a bit extreme but in my experience there are 2 types of developers, The ones who get RxJs and the ones who don't!
and the ones who get RxJs won't write a single line of imperative code event if you point a gun to their heads :))
I actually try to avoid subjects whenever possible. And if I do use them, I try to put them is a place that their accessability is very limited.
It will be more readable if you use function in scan vs a lambda expression
I think one major benefit of Declarative code is, how easy it is to make changes. Clients can be fickle and might want you to change how a component works. With declarative code, it is so easy to make changes because all logic is contained in a box. Eg: Load employees only when the event from child component is fired and there is at least 1 filter setup and input parameter is set to true. With imperative code, this means tons of if's and else's and multiple areas calling the loadEmployees function. With declarative code, this is just combineLatest. Latter is much more open to modifying the logic with minimal bug risk.
For some people code can be seen as imperative, while for others it's declarative. It's the same debate as "too little abstraction for some people, while for others it's abstracted enough already or even too much"
For me personally - the example you've presented with signals is actually declarative enough, because you're not manually updating value in every single place you need to update it
but rather have some function that listens on given value change or some other action, to automatically perform some effect. And that's my sweet spot
My biggest problem is that a lot of Angular devs say that in order to write code declaratively, you have to use RxJS... which actually adds a lot of complexity, because it shrinks and hides a lot processes into small... weirdly named function calls which you need to learn, rather than just simply declaring your reactive value and declaring how it should be updated
Definitely don't want to enforce any dogmatism around how declarative code should be written, I like the idea of doing whatever works best for you/your team and evaluating that over time. By my definition of declarative (which seems to line up reasonably well with yours, i.e. "declare a value and how it is updated over time") I am one of those who thinks you do need RxJS (or something else) to code declaratively in Angular. It will be a bit better now with signals because you can do some declarative stuff out of the box, but as soon as you start touching async stuff you would need RxJS if you wanted to keep things declarative in the sense that you can understand what something is just by looking at its declaration. RxJS handles the "how it is updated over time" part for asynchronous events, otherwise things need to be set imperatively when some async process finishes.
People don't know how bad their imperative codebase really is until they switch to working in a declarative codebase. A mature imperatively designed codebase is a huge headache to troubleshoot. Having your functionality encapsulated frees up a lot of mental bandwidth that gets spent trying to find and remember all of the different places where something gets updated.
True. It's like JS vs TS. Yes, its harder to go with types but it gives you more time to think about you want to accomplish rather than trying not to break something because you chose wrong value
Bro speaks only-facts language 🗿
You didn't sell me on declarative coding.
firstValueFrom!
Start using Elm then you will never write single imperative line of code ever again. Even in angular
I don't get this diagrams. "Understanding how things change" unless function that sets myValue is not using global variables. You can easily reason what would be myValue = fn( a, b, c ) as it depends on arguments. Code looks more like this fn( ... ) { fn1; fn2; fn3; } it's almost exactly the same as left side where you have show as encapsulated code. Both example look bad, structure, naming. Overall code composition and architecture is dumb. Why you have to load employees to add or remove one. This is biggest problem in software accidental complexity that create this whole clusterfuck code.
When you say you do it because “it is easier”, that is not a fact it is an opinion.
If a person prefers declarative then it will be easier and they will enjoy coding it more, which is a positive for them, but the same goes for someone who prefers imperative.
It’s really mostly about personal preference.
To be a good engineer I believe you need experience with both so that you can understand both types of code and can work productively in teams that use either or both approaches.
Sure, but my point is (at least I think it is, it's been a while since I've seen this video) that people are coming to an opinion on imperative vs declarative code without really understanding what declarative code is or the benefits it might bring. People often dismiss declarative code entirely because it just looks more complicated, so I'm highlighting the point that I do it because it is the easier option given the bigger picture (and yes, we can tack a "easier, for me" on there)
And I don't really think it falls under personal preference, I think the ramifications of one approach or the other are quite significant (versus say how you like to name your variables) - technically still a preference I guess, but to me that would be like labelling all of software architecture concerns as personal preferences
Your declarative code is not declarative, it's declarative/functional at best. You are still describing how to get to your result as opposed to just describing what your result should be. HTML, Prolog, and SQL are example of declarative programming. More functional javascript (which it should be anyway given JS is just Lisp disguised with a C-like syntax) is far from being declarative.
Agreed. I'm probably 70% declarative and 30% imperative personally.
I think being imperative at the "extremities" of your apps reactive graph is not a big deal (and can be easier), so way up where data first flows in, or at the very end where data is flowing out. Imperative in the middle makes a mess.
It's not Difference between Imperative vs Declarative Code. Your both Code Snippets are Declarative. 😓😓
Why do you think the example I gave as imperative is actually declarative?
@@JoshuaMorony If Second One is imperative, Does React and Solid Apps are written Imperatively?
@@ajayraja6636 I don't really know how people are writing React and Solid apps, but generally you are able to write both declarative and imperative code within the same framework. The imperative example I gave is imperative because 'employees' is set after its declaration, whereas with the declarative example 'employees$' is fully defined at the time of declaration.
@@ajayraja6636 yeah React and SolidJS are still somewhat imperative. They're reactive only after state is set. For a 100% reactive example check out CycleJS
@@JoshuaMorony I can't fully explain here due to RUclips Comments Limitations. Therefore I provided a Github Gist where I explain it. Here the link gist.github.com/AjayTheWizard/248a6fabed3389a2b0d81370dcdc6bf8
Declarative code is awesome. rxjs is over-complicated
Months ago you convinced me to build an app with reactive declarative code. I just finished a proof of concept and I have a couple of thoughts/tips which you and your subscribers might find useful :)
- It was not easy to change my mental modal, but I am happy that I did!
- Especially in the beginning what you can do, is to write the code imperatively and ask ChatGPT to refactor it in a "reactive declarative" way.
- Since it is not a perfectly defined and popular concept, it is helpful to give ChatGPT one or two examples. Also you might need a bit of a back and forth, to make it work in a way as Joshua does.
- ADD COMMENTS!! This will help you understand your code much better, especially on the next day or day after. Also it helps to learn the concepts and helps other developers to understand it.
- Once you've done this a couple of times, you'll have a better understanding, e.g. what kind of operators to use when.
- You have to understand that you can make anything a stream, e.g.
1) getting data and showing it as a list
2) filtering the list and only showing the filtered results
3) deleting a list item and updating the list
... and combine those streams into one observable to which you can subscribe via an async pipe!
4) Sometimes it might feel like an overload, but once you get the concepts you will appreciate your own code much more.
I only have two mid-level concerns:
1. Testing - I'm not sure how well it works to test components, especially those which have multiple streams
2. Newcomers - it's definitely harder for people who are not familiar with this coding style, but if you add comments and the people can use ChatGPT I think it is not doable and worthwile.
@Joshua I'd love to hear your thoughts, especially in regards to testing! (Cypress)
Thanks for sharing your experience, very interesting! As for testing I've got a few videos on my channel around the topic (one specifically focuses on the idea whether reactive code is harder to test), but in general I've never really faced anything annoying (probably mostly because I use observer-spy for just about everything)