[ home / rules / faq / search ] [ overboard / sfw / alt ] [ leftypol / edu / labor / siberia / lgbt / latam / hobby / tech / games / anime / music / draw / AKM ] [ meta ] [ wiki / shop / tv / tiktok / twitter / patreon ] [ GET / ref / marx / booru ]

/tech/ - Technology

"Technology reveals the active relation of man to nature" - Karl Marx
Name
Options
Subject
Comment
Flag
File
Embed
Password(For file deletion.)

Not reporting is bourgeois


File: 1756309952917-0.png (323.89 KB, 677x453, ClipboardImage.png)

File: 1756309952918-1.png (405.14 KB, 1100x688, ClipboardImage.png)

 

How do you go about choosing variable names?
To me this seems to be the atom of abstraction.
So there should be a lot to talk about if we can overcome the scale.

Was recently reading some about DDD [^1] the basic idea being as follows:
- Use ubiquitous language: the language used in the business domain, in coordination with experts
- Divide the language into contexts which assign a unique meaning to each word.
Typically this means division into microservices or separate programs, but it might work okay with modular monoliths.

At a more basic level there is the division of variable names grammatically. [^2]
- transitive verb with direct object: function
- linking verb with predicative adjective: predicate
- transitive verb: method

- singular noun-phrase: non-boolean datum
- predicative adjective: boolean datum

- plural: when multiple entities
- abbreviation: when scope is small

The idea with both of these is to reuse existing language processing for programming.

Anyone have any refinements?

:[^1] https://www.thoughtworks.com/insights/blog/domain-driven-design-neednt-be-hard-heres-how-start
;[^2] https://dev.to/somedood/a-grammar-based-naming-convention-13jf

Hungarian notation is underated

>>30995
There's an interesting occurrence when renaming variables in scope.
We tend to name variables teleologically based on use rather than identity.
So we might have multiplier and multiplicand rather than a integer representing something.
This is actually somewhat poetic, as if using a stick as a sword made it so.

>>30997
Is this mostly for dynamic languages?

>>31000
Mostly C++ in practice
Now that you mention it though

Acceptable variable names:
i, j, k, n, m for integers
s, p for strings/pointers
foo, bar, foobar if management tracks performance by characters

>>30999
This isn't exactly teleological because the "purpose" keeps changing.

>>30995
Anyone else think that the DDD example in the second picture doesn't actually use ubiquitous language? The .*Repository parameters in particular, (but also perhaps the notion of a shoppingCartId as opposed to an articleId which presumably exists, if it's an article of clothing). Wonder if this would be a good reason to choose ActiveRecord over the DataMapper pattern.

>>30995
>Typically this means division into microservices or separate programs, but it might work okay with modular monoliths.
If this would work with microservices or separate programs it would work with modular monoliths just by utilizing nested namespaces, which are equivalent for these purposes.

Guess determining namespaces isn't too far off topic of naming, it's often just a dot.
One approach to DDD is this idea that there should be "a thin service layer and a rich domain model". [^1][^2]
It typically involves more layering, but really find this rather confusing.
Sort of made progress in this direction in a few applications where all the validation etc. was inside of the domain model.
It's also immediately apparent that a traditional ORM with this technique are rather incompatible with functional core.
Overall don't know where to start when it comes conceptualizing the separating out of modules.

:[^1] https://medium.com/@inzuael/anemic-domain-model-vs-rich-domain-model-78752b46098f
:[^2] https://martinfowler.com/bliki/AnemicDomainModel.html

>>31015
Wonder if a rich functional service layer and a thin mutable domain model would be better? The downside seems to be bad locality of behavior, but better testability. Seems the one is far more important than the other, right? Assuming that the domain model must be mutable…

>>31018
Hmmm
This is a bit oldschool but it'll save you a fair bit of work later, get some paper and a pen and sketch out your architecture for your project?

>>30995
> How do you go about choosing variable names?
Honestly, I go 99% just by vibes.
The only rules I follow are:
- Try too append "s" to the collections
- Prefix "has" or "is" to bools
And that's kinda it.
My only real strategy to improve undesirability is to break down the program a lot, in functions and namespaces. Also I try to keep the functions pure, if I can.
>>30997
Maybe in C++ and Java where it can not be exactly clear if you're referencing a class-wide or local variable. Tbh I just use this or the equivalent most of the time.

I haven't made anything big enough to need a convention yet. Could make a game so I'll have to.

>>31022
With vibes we all enter the world, and as vibes we will all return.

>>31020
>>31026
Think my applications are generally to small to benefit from functional shell imperative core. If all you're doing is serializing input with validation at the domain model and rendering there's really no place for it.

>>31022
Agree with pluralising lists and prefixing has/is on bools.

I will add that "count" can be a useful word for integers, e.g. where a list of objects representing different houses might be named "houses" if I wanted to have a function that took the length of that list as a parameter I might name that parameter "house_count" or "houseCount" depending on convention.

>>31003
>i, j, k, n, m for integers
only 5d unit vectors? (scoffs) amateur

>>30996
Think found an example of functional core, imperative shell in my ~/Software directory, metainfo.py in my torrent client.
Basically this object which maintains the overall state of the torrent (excluding the message handlers) is initialized by a set of twelve static method calls.
However, theoretically the object could be recreated every time its state would otherwise need to change and it could be frozen.

It still reads from disk and the network which means that it's not easily tested.
Wonder how the network and filesystem aware parts of the protocol could be implemented in such a way as to separate out the actual IO?
For example how do you test that a piece is properly received without performing the IO to write and receive a piece when there's state to be maintained for the connection etc.?
Should think some about a sans-io [^1] torrent client guess.

:[^1] https://sans-io.readthedocs.io/how-to-sans-io.html#how-to-write-i-o-free-protocol-implementations

>>31045
For reals, when you deconstruct a list, are the names
- h t (head, tail)
- a d (car, cdr)
- v vs (or a as, x xs, etc.)
or something else?

>>31053
Think prefer "x : xs" of these even though it's less descriptive than the other two (what is "x"?), it generalizes to arbitrary collections, and iterators better, and when used generically allows for more description, for example "for file in files".

>>31053
Looking at my imageboard arsvia's code it seems like there's room to pull validation logic into the data model and to factor out this functionality into static methods for testability. This could be done using SQLAlchemy validators [^1] or custom initializers.

:[^1] https://docs.sqlalchemy.org/en/20/orm/mapped_attributes.html#simple-validators

>>31056
>pull validation logic into the data model and to factor out this functionality into static methods for testability
This is actually really cool to me! Arsvia could have the service layer virtually deleted. The entire program can be written as rendering and object initialization/mutation with static IO free methods handling the bulk of init. There's probably some errors in the attached image, but the idea was applied to a scratch buffer with the image object. The init method acts as a imperative shell for the functional core of the static private methods.

>>31057
Obviously the stupid calls to the validation logic in __get_mime should be validators for the size and mime.

File: 1756414049875.png (42.13 KB, 520x520, ClipboardImage.png)

I try to use descriptive names for functions, global, records and long-lived state variables in an ugly main function. Otherwise i try to avoid long variable names, because they clutter the code and relying on them means your code isn't clear enough on its own. The same for comments, if you need to explain the minutiae of your code, you better have good reason to!
>>31003
This, except i use p-w for pointers and occasionally c-e, h, l-m and ll as pseudo hungarian warts.

>>31057
How did you make VSCode look like that?

by purpose for primitive types

int counter; uint id; etc

by type name for user defined types, if scope already has a variable named like the type, then by purpose.

user user; user login_user;

works for me in most cases.

>>31068
It's https://helix-editor.com/ in https://alacritty.org/ with https://github.com/microsoft/pyright and https://github.com/blopker/codebook it just sort of works; though it's missing some commands from GNU Emacs.

>>30999
>>31004
Think this is related to performativity. Through repeated use an object can be assigned a concept. Like a cave under a rock can be named a home when so used. It's strictly anti-essentialist. Makes me wonder about E-Prime-esque avoidance of essentialist language. Am not sure about is at the moment, does it denote essential properties? Even something like "it is gray" breaks down and might take on the meaning of old rather than the color. Would it be more correct to say "it feels gray"?

>>31098
How does this work with declaration not in local scope, like a top-level function declaration. Surely a top-level function is named by its definition and not its use, though it could be rebind it to a different name depending on use.

>>31101
If you're designing your API in advance or via wishful thinking use is more relevant.
It may be that performativity cautions against "essentialist" programming of using depth-first naming.
This top-down process is however decidedly not how my programming process looks.
How else could you end up exploiting "one weird trick the pros don't want you to know" to implement API's like the following:

class Base(DeclarativeBase):
    ## converts an object as a dictionary.
    def as_dict (self):
        return {c.name: str(getattr(self, c.name)) for c in self.__table__.columns}

def to_json (object):
   return json.dumps(list(map(lambda a: a[0].as_dict(), object, default=str)))

This is probably not good.

>>30995
Recently, I generally follow what these articles lays out:
https://chrisdone.com/posts/german-naming-convention/
https://degoes.net/articles/insufficiently-polymorphic

I try to go for full names if possible. I use single letters when the code is polymorphic and full names don't make sense. I avoid acronyms almost completely.

>>31109
>https://degoes.net/articles/insufficiently-polymorphic
Never would have thought to add polymorphism to make a function more specified.
It's not strictly a program refinement because the postcondition is weakened along with the precondition.

File: 1756571698556.png (1.08 MB, 996x1323, ClipboardImage.png)

>>31098
>Am not sure about is at the moment
Find it difficult to reconcile an essentialist framework with other aspects of my thinking so as to even start to reason about "is". The problem may be even more general applying to the "gnomic aspect" e.g. "He plays the guitar." Specifically this language appears to describe a process who's constitutive properties do not change.

Removal of the gnomic in general and especially in English appears impossible. You can however reinterpret the gnomic aspect as the habitual, sense they're syntactically nearly identically. This aligns almost exactly with performativity in that what something is (in the gnomic aspect) is how it habitually acts.

The present tense of verbs in English works to express action in a habitual hypothetical present. Even "two plus two is four" might be habitual.

>>31115
What about adjectives?

>>31109
>https://degoes.net/articles/insufficiently-polymorphic
Doesn't the example completely contradict the whole thesis? Don't tell me "k" and "v" are not short for "key" and "value"?

>>31116
Many of these are relational definition of a subject in contrast to others.
They exist to single out the topic for predication or identity.

The real problem turns out to be the words themselves and not grammar.
But this just circles back to >>30999 (You), and >>31098 things are as they perform.
Meaning A is B just means A habitually performs as B.
"That stump is a good chair." ~= "That stump habitually performs like a chair that is good."

There's however no longer any relevance to programming one can think of.

"Mathematics is an experimental science, and definitions do not come first, but later on. They make themselves, when the nature of the subject has developed itself." - Oliver Heaviside

File: 1756582253161.pdf (69.95 KB, 180x255, TeachingMathematics.pdf)

>>31123
> Mathematics is a part of physics. Physics is an experimental science, a part of natural science. Mathematics is the part of physics where experiments are cheap.

File: 1756656814913-0.pdf (1.83 MB, 197x255, AbelNew.pdf)

>>31124
Was looking for something like Serg Lang's "Basic Mathematics" from V.I. Arnold's perspective.
Found the attached (AbelNew.pdf), which aims to explain group theory to high-schoolers.
Skimming it didn't actually see much of what it sought above a problem orientated approach.
Perhaps the problems are more geometrical than most and thusly more "physical".
The problems don't come before the definitions to establish that our abstractions map to reality.
Such focus as that would mirror TDD or REPL based development.

This of course could be done in an outside-in or top-down manner. [^1]
And if it was it might remind of "A Radical Approach to Real Analysis" which starts with the "why".
Our problems not only map to reality, but our search is justified.
In software this means we only write what we need to write.

:[^1] https://outsidein.dev/concepts/outside-in-tdd/

>>31125
It should be noted little mathematics is currently in my head so my thoughts should be taken with a grain of salt.

>>31057
There's one more method that can be pulled into the functional core in this example. Namely the conditionals that are responsible for generating the thumbnail once the setting of self.thumbnail and the saving of thumbnail_image.save(filename=thumbnail_path) are pulled out. How would you go about testing the thumbnail generation, and the persistence of the images in this example? Guess you'd still need to testing image files, and configure a save location. This is now coupled to the database however, because it's in the initialization of the ORM. Is the idea to pull out even parts of the imperative shell out from the initialization so that all that all it does is really initialization? The init would then simply be tested with the object as a whole. Refactoring in this way gives the following:

@staitcmethod
def __get_image_size (file):
	size = file.seek(0, os.SEEK_END)
	file.seek(0)
	return size

@staticmethod
def __get_data_mime (file):
	mime = magic.from_buffer(file.read(2048), mime=True)
	file.seek(0)
	return mime

@staticmethod
def __get_filename (file_data, file):
	extension = ''.join(pathlib.Path(file.filename).suffixes
	return sha256(file_data).hexdigest() + extension

@staticmethod
def __get_location (file_name):
	return os.path.join(config.IMAGE_RELATIVE_FOLDER, file_name)

@staticmethod
def __generate_thumbnail (image):
   height = round(min(240, 240 * image.height / image.width))
   width = round(min(240, 240 * image.width / image.height))

   image.sample(width, height)

   image_format = image.format if image.format != 'PDF' else 'PNG'
   thumbnail_name = sha256(image.make_blob()).hexdigest() + "." + image_format
   thumbnail_path = os.path.join(config.THUMBNAIL_FOLDER, thumbnail_name)

   return config.THUMBNAIL_RELATIVE_FOLDER + thumbnail_name

@staticmethod
def __generate_thumbnail_by_mime(file_name, mime)
	thumbnail_path = None

	if re.match("image/*", mime):
	   with Image(filename=os.path.join(config.IMAGE_FOLDER, file_name)) as image:
		  thumbnail_image, thumbnail_path = File.__generate_thumbnail(page)
		  thumbnail_image.save(filename=thumbnail_path)

	elif re.match("application/pdf", mime):
	   with Image(filename=os.path.join(config.IMAGE_FOLDER, file_name)) as image:
	      page = Image(image=image.sequence[0])
	      page.alpha_channel='remove'
		  thumbnail_image, thumbnail_path = File.__generate_thumbnail(page)

	return thumbnail_image, thumbnail_path 

@staticmethod
def __persist_thumbnail (file_name, mime):
	thumbnail_image, thumbnail_path = File.__generate_thumbnail_by_mime(file_name, mime)
	thumbnail_image.save(filename=thumbnail_path)

	return thumbnail_path

@staticmethod
def __persist_image (file_data, file_name):
	with open(os.path.join(config.IMAGE_FOLDER, file_name), "wb+") as disk_file:
	   disk_file.write(file_data)

# XXX: the check that there are the correct number of files must be handled by the constructor for
# the post.
def __init__ (self, file, post, board, user, address, spoiler):
	self.post = post
	self.board = board
    self.user = user
	self.address = address
	self.spoiler = spoiler

	self.size = self.__get_image_size(file)
	self.mime = self.__get_data_mime(file)

	file_data = await file.read()

	self.name = self.__get_filename(file_data, file)
	self.location = self.__get_location(self.name)

	# XXX: Persistence must be handled after validation of the object in the initialization functions,
	# but before generation of the thumbnail. 
	self.__persist_image(file_data, self.name)
	self.thumbnail = self.__persist_thumbnail(self.name, self.mime)

>>31145
Something that's still alarming to me is that in this paradigm all the validation logic is hidden from the initializer. This means there's no indicator that for example you've checked the file size is not too large before running the persistence, or reading in the file. You could add assertions that the size is initialized but it doesn't exactly encode.

>>31146
Maybe just a comment? Only downside is syncing. It is testable: create a too large file and initialize File then check if it was persisted.

>>31145
Am now confused. It seems like none of these private methods should be tested directly by common best practice of not testing private methods and testing behaviors not implementation details (so as to avoid having to rewrite tests upon redactor). Guess there's still some virtue in having a functional core, but it does seem greatly diminished. Anyone have any thoughts on this?

>>31148
This would imply integration tests. Unit tests divide up the state space make it easier to get comprehensive coverage of branches for example… (Even though the code you provided only has three branches.) Testing behavior does not imply only using integration tests. You could switch from private to protected methods and inherit the class for testing. The only method that's difficult to comprehensively test here is __generate_thumbnail. You can check dimensions for a variety of files but there's no real nonvisual way to check that the file has been generated correctly otherwise.

>>31149
Still can't decide about this. Maybe indeed because there's only three branches. It seems like a set of integration tests would work well. Need to think and probably experiment more.

>>31150
Its also much easier to TDD unit tests.

>>31145
There are still several bugs in this program because have just edited it in a scratch buffer with no tooling.

Start with Acceptability Tests.

# Validation Logic.
def file_too_large_fails ():
def file_wrong_mime_fails ():
def file_too_large_doesnt_persist ():
def file_wrong_mime_doesnt_persist ():

# Persistence Logic.
def file_persists_thumbnail_for_image_at_hash ():
def file_persists_thumbnail_for_pdf_at_hash ():
def file_persists_file_at_hash ():

Narrow using Unit Tests

def file_get_mime ():
def file_get_size ():
def file_get_filename ():
def file_get_location (): # originally missing.
def file_gen_thumbnail_skinny ():
def file_gen_thumbnail_wide ():
def file_gen_thumbnail_pdf (): # originally missing.

Conclusions

1. Unit tests are much clearer than the acceptability test.
2. They suggest a different interface than what was actually implemented. Namely this suggests pulling out the filename function.
3. The functional core becomes what the unit tests are applied to while the imperative shell is tested in the acceptability tests.
4. Nowhere is there a test that the proper interface (as the fields) exists. The design of this interface should be arrived at by higher level implementation.
5. The acceptability tests seem too big to properly lead to the implementation unlike the unit tests.
6. The unit tests do not directly encode the requirements unlike the acceptablity tests and so seem too small to get started.

Questions
1. Does this actually work in practice?
2. Would this lead to an excessively mocked test suite?
3. Would this lead to an excessively brittle test suite?
4. Am overall still lost…

>>31152
The experiment continues!

Couldn't the validation logic tests also be unit tests? e.g. in class-validator open the validator class and test the validate method. The persistence tests would also be unit tests, they would simply require more complicated data and call some of the higher level methods.

What does the red-green-refactor loop look like here? Besides that your integration tests basically suck (the purpose is to integrate (modules), not just to test the imperative core). You need to include tests of the module interface otherwise you're going to go green before you've satisfied the requirements. The obvious next question is what are the requirements? For all relevant pages:

def has_uploaded_file_size_in_units ():
def has_link_from_filename_to_uploaded_file_hash_in_file_directory ():
def has_thumbnail_link_to_file_hash_in_file_directory ():
def has_thumbnail_image_displayed ():
def has_thumbnail_image_maintains_aspect_ratio ():
def has_thumbnail_image_within_maximum_size ():
# Strictly UX tests:
def has_thumbnail_placeholder_for_unhandeled_mime ():
def has_thumbnail_spoiler_for_spoilered_files ():
def has_thumbnail_spoiler_click_unspoilers_thumbnail ():


The exact details that the thumbnail transformation be aspect ratio preserving and within certain dimensions seem to be more implementation details.

In other words because your app is so simple the integration tests fold into the UX tests, the only call site is the UX. With these UX tests written it's clear that your application would not run unless you had the correct functionality (with the exception that the thumbnail transformation might be erroneous).

This might be too many tests, but it's how this outside-in would have to work.

>>31154
Of course this assumes you're not using mocks for any of these.

>>31155
Continued to clean up the source of the sample. Was thinking more about names. Have come to the conclusion that avoiding trivial thoughts is fruitful. Where this is some combination of repetitive, irrelevant, or vacuous thoughts.

- repetitive: includes any repetition of thoughts of perception or feeling in verbal form.
- irrelevant: includes any thought which is based on a false association (including false statements such as those concerning the self) within some broad context (perhaps a set of goals.)
- vacuous: includes any thoughts that neither contain information nor prompt for further like some rhetorical questions.

These apply rather obviously to programming, but applying them to thought, if you can manage, seems to be a rather radical cognitive shift. LLMs rather dislike my second term "irrelevant", but it still seems important to me so long as it's interpreted rather liberally.

Programming to avoid these things ever appearing in the first place might bring us back to >>31125 "In software this means we write only what we need…" and the converse set of reasoning that perhaps this entails a top-down or outside-in design.

>>31162
Aren't all vacuous statements irrelevant by this schema? And all three (trivial thoughts too) could be thought of as statements not providing information content to any of our goals. These categories are still useful, because you don't really need to know your goals to apply them.


Unique IPs: 15

[Return][Go to top] [Catalog] | [Home][Post a Reply]
Delete Post [ ]
[ home / rules / faq / search ] [ overboard / sfw / alt ] [ leftypol / edu / labor / siberia / lgbt / latam / hobby / tech / games / anime / music / draw / AKM ] [ meta ] [ wiki / shop / tv / tiktok / twitter / patreon ] [ GET / ref / marx / booru ]