Jump to content
DavidW

Immutability and encapsulation in mod design

Recommended Posts

@Wisp Sure:

1. Using variable name of 'test'

 BACKUP ~ImmutableA/backup~
SUPPORT ~http://www.ImmutableA.com/forums~
VERSION ~0.1.0~

ALWAYS
    CLEAR_EVERYTHING
END

BEGIN "ImmutableA 1" NO_LOG_RECORD
    OUTER_TEXT_SPRINT test error
    PRINT "%test%"

BEGIN "ImmutableA 2" NO_LOG_RECORD
    PRINT "%test%"

The first component from above code will print "error", the second one will print "%test%" as expected.

2. Using variable name of 'MOD_FOLDER'

 BACKUP ~ImmutableB/backup~
SUPPORT ~http://www.ImmutableA.com/forums~
VERSION ~0.1.0~

ALWAYS
    CLEAR_EVERYTHING
END

BEGIN "ImmutableB 1" NO_LOG_RECORD
    OUTER_TEXT_SPRINT MOD_FOLDER error
    PRINT "%MOD_FOLDER%"

BEGIN "ImmutableB 2" NO_LOG_RECORD
    PRINT "%MOD_FOLDER%"

The first component from above code will print "error", the second one will also print "error". According to the readme " then reloads the automatic ones ...MOD_FOLDER..." so I expect that second component will print "ImmutableB" and not "error".

Share this post


Link to post

@subtledoctor Thanks, that's good example of actual usage. Not having "those 2-5 seconds for every component" is also valid point.

Share this post


Link to post
1 hour ago, subtledoctor said:

Sigh.  Not really looking for a debate.

Then you've come to a wrong place. This is an internet forum. People have been debating on these since before we were born and will continue after we're gone.

1 hour ago, subtledoctor said:

If CLEAR_EVERYTHING works for you, that's great.  Suggesting that there is only one way to skin this cat, or that your lazy simplistic simple way ( :p ) is somehow objectively better than another given way, seems ridiculous to me.

I didn't suggest that there's only one way. However, if there are multiple ways, it's either they are all objectively equal, or some are better. In particular, in software engineering, it is general consensus, with which I agree, that simpler is better. If function way works for you, great.

1 hour ago, subtledoctor said:

 And there were two fine answers which I guess bear repeating because you either didn't read them or didn't understand them or you found some other reason to ignore them:

1) "At a more conceptual level, I'd like my encapsulation to be built in to the way the code is structured, not forced explicitly. One of the main points of FUNCTIONs is to deliver this; why not use it?"

2) A disadvantage with CLEAR_EVERYTHING is that "you can't read in data in your ALWAYS that's to be used in any component."

These answers had responses in the following posts, which I guess you didn't read or didn't understand or found some other reason to ignore. However, I'll detail:

1) I literally explained in the post you've replied to.

2) Is not true.

1 hour ago, subtledoctor said:

But, you're wrong.  Functions don't break the idea of encapsulation.  They were specifically proposed as a way to achieve it.  Moreover, the point of encapsulation is that things can't get out of your component sandboxes; it's mot mean to keep anything from getting in.

I didn't say they did. You made that up.

And no, you are wrong about the point of encapsulation. It is to make sure stuff works the way it's supposed to, even when used in whatever funny way. Applicably to weidu components, however, it's really just semantics. Things that get in have to get out of another component first.

2 hours ago, subtledoctor said:

So at the very outset, the first time you install anything in the mod, it generates an array of arcane spells and their associated scrolls (and also their schools).  Later, various components read from this array in order to correctly patch the spells and scrolls.  We feed that data into each component for use by the component; if we did CLEAR_EVERYTHING every time, we would have to dynamically generate that data every time.

...

If you tell them "thou shalt put CLEAR_EVERYTHING in your ALWAYS block" and later they decide to implement something like what Tome & Blood does, it won't work for them and they might not understand why.  Dropping things into functions (again, adding a single line of text at the beginning of each component) precludes the possibility of that difficulty, for exceedingly low effort.

I, too, don't understand why. If it's generated by any component launched first, I assume it's in the ALWAYS block. If it's there, it'll work. Please explain.

2 hours ago, subtledoctor said:

as I say, I haven't seen any valid arguments for why clearing the data and re-generating the array multiple times would be any better.

Have you heard the phrase "the best code is no code at all"? Do you agree with it or not?

Share this post


Link to post
1 hour ago, qwerty1234567 said:

Then you've come to a wrong place. This is an internet forum. People have been debating on these since before we were born and will continue after we're gone.

Lol, when were you born? :laugh:

Quote

I didn't suggest that there's only one way. However, if there are multiple ways, it's either they are all objectively equal, or some are better.

...And what you find to be subjectively better just happens to be objectively better, too.  Probably happens all the time, right? How very convenient. OK nazi. 

Quote

I didn't say they did. You made that up.

You said wrapping code in functions “breaks encapsulation.” As far as how terms have been defined in this thread, that is (objectively! :p ) wrong. I can only respond to what you said; if you didn’t express yourself well, don’t blame me. 

Quote

 Things that get in have to get out of another component first.

This too is wrong.

Quote

I, too, don't understand why. If it's generated by any component launched first, I assume it's in the ALWAYS block. If it's there, it'll work. Please explain.

Yes. And I already explained it. (AL|EN got it.)  If you failed to comprehend it, you can keep trying or we can just move on. 

Quote

Have you heard the phrase "the best code is no code at all"? Do you agree with it or not?

You are suggesting that people use code. Heavy-handed code, which they may not fully understand, in an ALWAYS block that permits no exceptions. That is FAR from “no code.” You are effectively suggesting adding one line of code at the beginning of every component. (That is what ALWAYS does after all.) Which is precisely as much extra code as I suggest. So I remain unconvinced that what you advocate is actually any simpler. 

Edited by subtledoctor

Share this post


Link to post
On 9/18/2018 at 4:08 PM, DavidW said:

/// Always block 

/// Stuff to do once 

ACTION_IF !VARIABLE_IS_SET always_block_called_already BEGIN 
	OUTER_SET always_block_called_already=1 
	[INCLUDE function and macro definitions, set variables, read in game data, or whatever] 
END 

// stuff to do for every component [As little as possible! - because everything you put here violates encapsulation]

 

I'm so stealing this...but question...the mod I'm copying from (yes...I cheat) has this in the always block:

   ACTION_DEFINE_ARRAY mymod_noconvert BEGIN setup END
   ACTION_DEFINE_ARRAY mymod_reload BEGIN game cases END

   LAF HANDLE_CHARSETS
      INT_VAR
         infer_charset = 1
      STR_VAR
         tra_path = EVAL ~mymod/languages~
         noconvert_array = mymod_noconvert
         reload_array = mymod_reload
    END

Why do the languages need to be converted every time?  Or do I not understand what this is doing - totally possible, actually ... I really don't understand what this is doing.  LOL  EDIT: They DON'T need to  be converted every time.  I've tested it.  So I've now put mine into a subsection that gets run only once...in the section that gets run every time.  LOL - How oxymoronic!

What actually is needed to be run always, other than loading library tpa files that contain handy functions? EDIT: Do they?  Why?  Wouldn't loading them once be sufficient?  EDIT EDIT:  No they don't.  These too have be put into my oxymoronic section.  But that still leaves the question: What actually is needed to be run always?

Sorry to resurrect an old portion of this thread, but I'm late to the party and am trying to catch up.

Edited by Lauriel
Fixed typos

Share this post


Link to post

I want to thank everyone that participated in this thread.  I learned SO much!

Share this post


Link to post
6 hours ago, Lauriel said:

..

Why do the languages need to be converted every time? 

Well, they need to be... when you have a conflict of letter/character types. Imagine a Russian .tra file using English characters. The text means nothing in English, but will translate into Russian when it's installed.

Share this post


Link to post
2 minutes ago, Jarno Mikkola said:

Well, they need to be... when you have a conflict of letter/character types. Imagine a Russian .tra file using English characters. The text means nothing in English, but will translate into Russian when it's installed.

And that needs to be rerun for every component in the install?  Just clarifying...

Share this post


Link to post
1 hour ago, Lauriel said:

And that needs to be rerun for every component in the install?  Just clarifying...

Well yes, if you want to have the same translation to the @1 in the seguential install. You could also go with ahh, it doesn't matter what was installed before and use those as the determinants, and so what if they weren't translated. Yet, weidu will then fail to install that component... so yeah. It's a few kilobites in RAM.. and we today have less than 1Kg ram sticks with 16Gb's. Rather than the 5Mb/500Kgs one from the 1950's.

For example, the Russian BGT-weidu setup.tra starts with:

////////////////////////////////////////////////////////////////////
//Items -- most provided by bg1.tra
////////////////////////////////////////////////////////////////////
@200000 = ~Ñòàòóÿ Èçìèðû~

//@23967 - change Blunt Weapons to Mace
@200001 = ~Áóëàâà +2: "×åðåïîëîì Êðîòàíà"
Äàæå ó îðä áûëè ñâîè ãåðîè, è õîòÿ â öèâèëèçîâàííîì îáùåñòâå èõ çà÷àñòóþ äåìîíèçèðóþò, äåÿíèÿ èõ îò ýòîãî íå ñòàíîâÿòñÿ ìåíåå âïå÷àòëÿþùèìè. Êðîòàí áûë èñêëþ÷èòåëüíî óìíûì îðêîì - íàñòîëüêî, íàñêîëüêî ýòî âîîáùå âîçìîæíî ñðåäè ïðåäñòàâèòåëåé ýòîé ðàñû. Îí êîìàíäîâàë îáúåäèíåííûì ëåãèîíîì îãðîâ, îðêîâ, õîáãîáëèíîâ è ïðî÷èõ òâàðåé â Ãîä Ïðîïàâøåé Ãîñïîæè, 1241ËÄ. Ãîâîðÿò, ÷òî èìåííî â ýòîì ãîäó áàíäà îðêîâ-ðàçáîéíèêîâ ïîõèòèëà è óáèëà òåòèðñêóþ äâîðÿíêó. Îòâåòîì âëàñòåé áûë ïðàêòè÷åñêè ïîëíûé ãåíîöèä îðêîâ â þæíûõ ïðåäåëàõ. Êðîòàí îðãàíèçîâàë îáîðîíó, ÷òîáû ñïàñòè ñâîé íàðîä îò òîòàëüíîãî èñòðåáëåíèÿ. Åìó ýòî óäàëîñü, õîòü îðêàì è ïðèøëîñü â èòîãå èçðÿäíî ïîòåñíèòüñÿ ñî ñâîèõ ïðåæíèõ òåððèòîðèé. Ñàì Êðîòàí ïîãèá óæå ïî÷òè ïîä êîíåö êîíôëèêòà, à åãî ãîëîâà áûëà íàñàæåíà íà êîë è âûñòàâëåíà íà îáîçðåíèå íà òîì ñàìîì êëàäáèùå, ãäå áûëà ïîõîðîíåíà óáèòàÿ ðàçáîéíèêàìè ìîëîäàÿ ëåäè. Ñàìè îðêè â ñâîåé èñòîðèè íàçâàëè ýòî âðåìÿ "Ãîä, êîãäà âñå çàøëî ñëèøêîì äàëåêî".

ÏÀÐÀÌÅÒÐÛ:

THAC0:  +2 áîíóñ
Óðîí:  1D6 +3
Òèï óðîíà:  äðîáÿùèé
Âåñ:  7
Ôàêòîð ñêîðîñòè:  5
Óìåíèå:  Áóëàâà
Òèï:  1-ðó÷íîå
Íå ìîãóò èñïîëüçîâàòü: 
  Äðóèä
  Ìàã 
  ×àðîäåé
  Âîð
  Ìîíàõ
  Ïîâåëèòåëü çâåðåé~

None of that is Russian, it's what the non-Latin characters turn into when read in Latin(well, technically in win-1252).

Edited by Jarno Mikkola

Share this post


Link to post

@subtledoctor

Quote

My takeaway from this thread is that the answer is NO.  Put the component into a .tpx file, sure, but also put it inside a function

But if the tp2 file contain only single component, there is no point of using function, right?

Quote

We feed that data into each component for use by the component; if we did CLEAR_EVERYTHING every time, we would have to dynamically generate that data every time.

One of the valid alternative would be: using ALWAYS to dynamically generate required data and store it inside "weidu_external\workspace". Then, each component can read the data without generating it again.

I"m just thinking loud.

Share this post


Link to post
On 2/17/2020 at 2:49 AM, subtledoctor said:

You said wrapping code in functions “breaks encapsulation.”

No I didn't. You made that up, again. I won't bother to go over the whole of your post, as you didn't answer questions and didn't provide examples supporting your points.

I think you argue in bad faith. You are welcome to prove me wrong with actual code examples, actual quotes and supporting evidence. I'm not afraid to admit being wrong if I am. Are you?

Share this post


Link to post

Dude...

On 2/16/2020 at 1:21 AM, qwerty1234567 said:

But if for some reason you really need to pass variables between components, be aware that it breaks encapsulation. And if you're ok with that, then go LAF route."

If you are going to deny having said something, you might at least go edit the old post to cover your tracks :nono: 

Lol. Who’s arguing in bad faith again? Also, what month is it?

Share this post


Link to post
Posted (edited)
40 minutes ago, subtledoctor said:

Dude...

Heh, subtledoctor, thing is... he didn't say what you implie that he would have said. He said what he did, but that doesn't lead into breaking the encaptulation. What he said was that if you are OK with breaking encaptulation then you can go with JUST fuctions, not "functions break encaptulations". There's a difference.

See, even though all horses are mammals, not all mammals are horses.

Edited by Jarno Mikkola

Share this post


Link to post
Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...