DEV Community

Discussion on: Keep your code dumb

Collapse
 
joelnet profile image
JavaScript Joel

but lazy-init isn't necessarily bad, just how it was implemented here.

Totally agree. C# also has Lazy<>, what is important about C#'s Lazy<> is that it is labeled Lazy.

The main problem with this code example is that there is code that "performs work" behind a property. And properties should never "do work". That is what a function is for.

Collapse
 
mortoray profile image
edA‑qa mort‑ora‑y

I understand the sentiment behind "performs work", but I'm not sure it's a fixed rule. Let me give you a counter example.

At Fuse we have a UX syntax for declaring a UI, here's a really tiny made-up snippet.

<PageControl IsEnabled="false" Transition="none">
   <PurchasePage/>
   <ProfilePage/>
</PageControl>

These correlate directly to types and instances in the backing Uno/C# code. For example:

var pg = new PageControl();
pg.IsEnabled = false;
pg.Transition = TransitionType.None;

When the app starts up it constructs a UI from these obejcts -- they are live objects, forming part of the UI tree.

Now what happens if I do pg.IsEnabled = true. This is a rather complex property. In order for the control to be enabled it needs to have a few attached gestures, which install pointer handlers, and a few other things. As a programmer using our API you don't think about this much, you just expect the control to be enabled now.

It appears that in the domain of declarative programming the rule about accessors not doing work may not be valid.

Thread Thread
 
joelnet profile image
JavaScript Joel • Edited

In this instance, I would still prefer to use something like pg.setEnabled(true).

If obj.prop was a getter that hid some logic behind it, then in the case of code like this:

// Properties get used like variables, which could put you in hot water
// if there is complex code behind the getter.
doSomething1(obj.prop);
doSomething2(obj.prop);
doSomething3(obj.prop);
Console.WriteLine(obj.prop);

We would be executing that property logic multiple times. We do not have any idea of how heavy the property is without opening up the underlying code. If each get hid a database or api call, we could quickly get into trouble.

In this instance, it would be more clear that the underlying code is doing something more than just retrieving a value...

doSomething1(obj.getProp());
doSomething2(obj.getProp());
doSomething3(obj.getProp());
Console.WriteLine(obj.getProp());

... and that the code should be written like this:

var prop = obj.getProp();
doSomething1(prop);
doSomething2(prop);
doSomething3(prop);
Console.WriteLine(prop);

I prefer this because it gives me visibility about the complexity of the code without having to dig into it. It also gives me more control over when the program performs this work.

Of course there is no set rule and situations vary and this is my personal preference :)

Cheers!

Thread Thread
 
mortoray profile image
edA‑qa mort‑ora‑y

I would argue that obj.set_enabled(true) and obj.enabled = true are semantically the same. It would be a break in the programmer's expectations if this weren't true. set/get functions are just making up for a lack of accessors/getters in a language.

Setting enabled in my scenario doesn't do something everytime. I'd never argue for that. You can safely set it repeatedly to the same value and nothing changes, only if the value changes. In declarative programming, and reactive programming though, there are a lot of dependent variables. By changing one you can set-off a cascade of modifications.

Thread Thread
 
joelnet profile image
JavaScript Joel

I am opposed to getters and setters entering into JavaScript. I don't like them in C# either.

I would argue that obj.set_enabled(true) and obj.enabled = true are semantically the same.

I still have to disagree on this for the reason that I have been bitten multiple times by badly designed software that hid logic inside a getter. This was not known to me until I experienced performance issues which required me to dig into the library I was using only to realize this was not a property value that I was expecting, but a full blown function disguised as a getter. If this had instead been a function, I would have expected some type of logic to be inside.

Thread Thread
 
mortoray profile image
edA‑qa mort‑ora‑y

Because some people misuse a feature is a bad reason to dislike it. An idiot can just as easily write a function called get_name() that deletes your hard drive.

Thread Thread
 
joelnet profile image
JavaScript Joel

Valid point.

I have been stung by this before, so I definitely hold a bias. I also prefer functional designs over OOP, so there is a lot of OOP that I also dislike.

Thread Thread
 
janjuks profile image
janjuks • Edited

I would argue that obj.set_enabled(true) and obj.enabled = true are semantically the same.

I agree with this, but even more that setters/getters shouldn't be doing any work. I think that Joel didn't name it very good. That 'set' in method name is the part which makes them semantically the same. Maybe it's just me, but naming it obj.enable() would imply that there might be some work to be done and not just setting a value.

That being said, I have written that code myself where private variable would hold some raw data and getter would decode it only once when first needed. This post + just recently read Clean Code by Robert C. Martin reminded me of this ^_^

Thread Thread
 
joelnet profile image
JavaScript Joel

naming it obj.enable() would imply that there might be some work to be done and not just setting a value.

^ This :)