Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Linear Zoetrope
Nov 28, 2011

A hero must cook
Yeah, it's not really TDD unless you're doing the red green refactor dealio. Which doesn't mean writing with the intention to test afterwards is bad, it's just not really the definition of TDD.

Adbot
ADBOT LOVES YOU

vOv
Feb 8, 2014

Hey let's have this discussion again for the 10th loving time

Bongo Bill
Jan 17, 2012

vOv posted:

Hey let's have this discussion again for the 10th loving time

I hope that by clarifying terms early we have preempted confusion and arguing past each other.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Bongo Bill posted:

I hope that by clarifying terms early we have preempted confusion and arguing past each other.

Why would it help this time

Coffee Mugshot
Jun 26, 2010

by Lowtax
If there are no tests at all, writing tests is easy. Test that the program is deterministic by giving it golden input and output, if determinism is a feature of your program. The most difficult part of writing tests altogether is actually writing code that can be tested without turning it into a TestGeneratorFactory or whatever. Simple things like passing contextual values via a configuration could allow a test for your client to completely fake/instrument the server-side connection. And then at some point when you're satisfied with your internal regression tests, you probably want some integration tests with the expected users of your library/API/service. Again, what becomes difficult is defining an API surface/abstraction that is somehow amenable to tests which switch out every component not provided by the library. (Regression and Integration) Tests fall naturally out of well-written code IMO. On the other hand, refactoring poorly-written code and the poorly-written tests for it is a nightmare. Refactoring tests in general is difficult because many testing environments are non-hermetic. Tests are haphazardly modifying global state and the order in which the test framework decides to execute your tests could determine the output; i.e. data races exists across test cases. You might think you can extract a piece of test logic from one function only to realize the test setup itself is non-deterministic.

Mezzanine
Aug 23, 2009
I love doing tests, especially acceptance testing where you get to watch the screen blit around clicking like crazy. Back at my last office, I had a project ready to go so that when I needed to show someone from another department what we do, I'd hook up their iPhone to my work machine and have it run through all the tests on the device.

Coffee Mugshot posted:

Tests are haphazardly modifying global state and the order in which the test framework decides to execute your tests could determine the output; i.e. data races exists across test cases.

Don't most runners do the tests in a random order by default for this specific reason?

Mezzanine fucked around with this message at 23:08 on Aug 25, 2017

Coffee Mugshot
Jun 26, 2010

by Lowtax

Mezzanine posted:

Don't most runners do the tests in a random order by default for this specific reason?

This helps, but a test runner can only control so much of the test environment. If you have a program which tests a database or network connection by reading a particular socket on your machine from the environment, it is possible between two executions of the test runner that the global/test environment is "fixed" in such a way that give your tests the appearance of being correct. Perhaps a poorly-faked test relies on reliably reading and writing from a table somewhere. It could be possible that two different test runners are executing in different environments and their operations interfere with one another. This actually happens quite frequently when testing interop code: like a python library that calls a C binary. Anyways, the point is, not even a sufficiently clever test driver can save you from shooting yourself in the foot with poorly-written tests that demonstrate patterns found in poorly-specified code.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

vOv posted:

Hey let's have this discussion again for the 10th loving time

this thread is a giant xfail stain but nobody cares enough to fix it

Meat Beat Agent
Aug 5, 2007

felonious assault with a sproinging boner
Don't write tests. Don't write code.

boo_radley
Dec 30, 2005

Politeness costs nothing
Coding horrors: WONTFIX, build fail on test fail disabled, eat poo poo and blind refactor

Today's exciting adventure: we're learning how to code Apex, which is salesforce's exciting paean to versions of java past combined with the blind fuckery of multitenant systems design. Perhaps you'd like to use generics? Tough poo poo, idiot! They're not implemented in Apex, so get ready for sObject casts and type errors.

They also have a "CICD pipeline" that seems to be built around manual configuration in their ui, with a small portion of development supported by Maven.

Carbon dioxide
Oct 9, 2012

https://twitter.com/hmemcpy/status/897528863680602113

het
Nov 14, 2002

A dark black past
is my most valued
possession

Harik posted:

A brave new world of unicode parsing vulnerabilities. I'm honestly glad that I used php instead of perl for late 90s CGI work. As poo poo as it is it didn't train you that clever > *.

Reading perl reminds me of Sendmail's turing complete configuration language

This post is from a couple weeks ago, but at my first real job, we maintained sendmail-based mail systems and one of the things I wrote was sendmail cf that effectively used the destination address as a stack passing it between rulesets doing map lookups. It was weirdly satisfying to do though obviously gross.

Vanadium
Jan 8, 2005

Ranzear posted:

I'm concerned that you phrase it this way instead of 'I should put things in functions and call them from a main flow control.'

Functions have the undesirable property of always returning to where they were called from! You can't return through nested function calls directly! You need to write down every single argument and return value!

NihilCredo posted:

Sounds like you want a finite state machine tbh.

Maybe I want a real handy notation for them.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

Vanadium posted:

Maybe I want a real handy notation for them.

What's your stack? I can't imagine that writing an enumeration could be so annoying you'd rather fiddle with break statements.

For reference, I've refactored messy loops into FSMs in Visual Basic and I can assure you the thought "man, this enum and these functions are a little clunky, maybe I should go back to loops" never even manifested within the same galaxy cluster as my mind.

Workaday Wizard
Oct 23, 2009

by Pragmatica

het posted:

This post is from a couple weeks ago, but at my first real job, we maintained sendmail-based mail systems and one of the things I wrote was sendmail cf that effectively used the destination address as a stack passing it between rulesets doing map lookups. It was weirdly satisfying to do though obviously gross.



:thunk:

checks out

TheBlackVegetable
Oct 29, 2006

Vanadium posted:

Functions have the undesirable property of always returning to where they were called from! You can't return through nested function calls directly! You need to write down every single argument and return value!

Are you looking for something like F# computation expressions?

Happy case programming, no need to nest function calls in error checking if statements.

Ranzear
Jul 25, 2013

Vanadium posted:

Functions have the undesirable property of always returning to where they were called from! You can't return through nested function calls directly! You need to write down every single argument and return value!

I grew out of procedural programming a long time ago. Now I do something even worse. I have my own superbastardized idea of objects and classes that works in most languages and centers around serializability for netcode, particularly in javascript but it ends up being very cross-language.

I almost exclusively work in class-static functions with structurally-typed objects as arguments (really, more invokes duck typing with class mutation). Each function returns at least the first object argument for functional chaining.

A class works out to being the set of static functions that take the typed object as the first argument and the strictly-data definition of the necessary structure for that object. The most important rule is that there are no breakable references on the actual object, and more interestingly the set of static functions for a type can differ between client and server. Each object can maintain a list of its classes for checking, especially in non-typed languages, which are retained through serialization too. The class constructor for an object can also receive an object to mutate instead, appending to its types.

The fun part comes when you can just queue up object references to pass into a function, like Entity.Damage(Entity, DamageSource), and execute them later. This means stuff like tanks and projectiles all get to act, then damage gets resolved so nothing gets removed before acting, the key being that a Tank has a Collider class that also adds DamageSource for ramming damage (sets the value on impact), just the same as a Projectile simply has DamageSource.

This is my personal coding horror because of the things I leave wide open out of laziness, like how a mutating class might overwrite other properties and should probably instead have it's own namespace on the object. That and slapping all these objects into a singleton and serializing the lot to ram it through a network connection.

Anyway, don't need to write down arguments and return values if it's always a typed object :v:

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison

Ranzear posted:

I grew out of procedural programming a long time ago. Now I do something even worse. I have my own superbastardized idea of objects and classes that works in most languages and centers around serializability for netcode, particularly in javascript but it ends up being very cross-language.

I almost exclusively work in class-static functions with structurally-typed objects as arguments (really, more invokes duck typing with class mutation). Each function returns at least the first object argument for functional chaining.

A class works out to being the set of static functions that take the typed object as the first argument and the strictly-data definition of the necessary structure for that object. The most important rule is that there are no breakable references on the actual object, and more interestingly the set of static functions for a type can differ between client and server. Each object can maintain a list of its classes for checking, especially in non-typed languages, which are retained through serialization too. The class constructor for an object can also receive an object to mutate instead, appending to its types.

The fun part comes when you can just queue up object references to pass into a function, like Entity.Damage(Entity, DamageSource), and execute them later. This means stuff like tanks and projectiles all get to act, then damage gets resolved so nothing gets removed before acting, the key being that a Tank has a Collider class that also adds DamageSource for ramming damage (sets the value on impact), just the same as a Projectile simply has DamageSource.

This is my personal coding horror because of the things I leave wide open out of laziness, like how a mutating class might overwrite other properties and should probably instead have it's own namespace on the object. That and slapping all these objects into a singleton and serializing the lot to ram it through a network connection.

Anyway, don't need to write down arguments and return values if it's always a typed object :v:

i didn’t know star citizen devs posted here

boo_radley
Dec 30, 2005

Politeness costs nothing

uncurable mlady posted:

i didn’t know star citizen devs posted here

Seriously, that's sort of "source your quote" territory

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde

sucks because not lazy

Bash code:
repl()
{
	local from="$1" to="$2" c buf
	while read -n 1 c; do
		buf+="$c"
		if [ "${#buf}" -gt "${#from}" ]; then
			echo -n "${buf:0:1}"
			buf="${buf:1}"
		fi
		if [ "$buf" == "$from" ]; then
			echo -n "$to"
			buf=
		fi
	done
	echo -n "$buf"
}

roman()
{
	yes I | tr -d \\n | head -c "$1" |
	repl IIIII V |
	repl IIII IV |
	repl VV X |
	repl VIV IX # etc.
	echo
}

Gazpacho fucked around with this message at 00:27 on Aug 27, 2017

Vanadium
Jan 8, 2005

TheBlackVegetable posted:

Are you looking for something like F# computation expressions?

Happy case programming, no need to nest function calls in error checking if statements.

No that's just monads, I really want a respectable-looking syntax for goto.

Vanadium
Jan 8, 2005

Ranzear posted:

I grew out of procedural programming a long time ago. Now I do something even worse.

I'm... not sure this is what I'm looking for but do you have some sample code?

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde

Vanadium posted:

No that's just monads, I really want a respectable-looking syntax for goto.
It kinda sounds like you want a compiler that can guess what you ambiguously want in a given flow situation.

Absurd Alhazred
Mar 27, 2010

by Athanatos

Gazpacho posted:

It kinda sounds like you want a compiler that can guess what you ambiguously want in a given flow situation.

Doesn't everyone?

Vanadium
Jan 8, 2005

What no I'm happy to be explicit, I just don't want to be verbose.

Ranzear
Jul 25, 2013

Vanadium posted:

I'm... not sure this is what I'm looking for but do you have some sample code?

Vanadium posted:

You need to write down every single argument and return value!

I was more responding to this part of your gripes, not the goto part. If you extract the methods of a classical object into static functions (and pass the appropriate object back into it) you can do procedural or even functional programming on fairly discrete data. There's no real need to return anything because you're just passing a big ol' chunk of state around.

The way you could utilize this is to create an object that represents your state machine then call functions on it, always as the first argument. This is kinda how you shoehorn state into Haskell.

But yeah, my special brand of heresy deserves to be in this thread.

fritz
Jul 26, 2003

Gazpacho posted:

sucks because not lazy


Nobody ever defeated Sheng Long by being lazy.

TheBlackVegetable
Oct 29, 2006

Vanadium posted:

What no I'm happy to be explicit, I just don't want to be verbose.

I'm curious now. What's it look like in pseudo code?

Absurd Alhazred
Mar 27, 2010

by Athanatos

TheBlackVegetable posted:

I'm curious now. What's it look like in pseudo code?

I'm imagining something like:

C++ code:
struct A
{
	int x, y, z;
}
struct B
{
	float u, v;
}
struct C
{
	bool isEnabled;
}

class Obj1
{
public:
	A a;
static void doThing(Obj1& obj)
}
class Obj2
{
	char[sizeof(A)] padding;
public:
	B b;
static void doOtherThing(Obj2& obj);
}
class Obj3
{
	char[sizeof(A)+sizeof(B)] padding;
public:
	C c;
static void doYetAnotherThing(Obj3& obj)
}
class ObjFull
{
public:
	A a;
	B b;
	C c;
}
And then populating an ObjFull and calling, say, doYetAnotherThing(reinterpret_cast<Obj3&>(objFull)).

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

Ranzear posted:

I was more responding to this part of your gripes, not the goto part. If you extract the methods of a classical object into static functions (and pass the appropriate object back into it) you can do procedural or even functional programming on fairly discrete data. There's no real need to return anything because you're just passing a big ol' chunk of state around.
It sounds as if you are emulating the way we used to emulate object-oriented programming in non-OO languages, in an OO language.

Ranzear
Jul 25, 2013

Zopotantor posted:

It sounds as if you are emulating the way we used to emulate object-oriented programming in non-OO languages, in an OO language.

Yep, but as stated above it's for serialization. I abuse enumerability to hide properties from it too.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
just do whatever you want as long as you're not working with one or more other people

but if you are working in a team (or you might be in the future) and you're doing something completely unrecognisable to any ordinary person who knows the language you're working in, then you should probably be prepared to be told to go gently caress yourself

Vanadium
Jan 8, 2005

TheBlackVegetable posted:

I'm curious now. What's it look like in pseudo code?

Closest I can actually visualize is llvm ir basic blocks w/ their terminating instructions.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
uhhh just so you know, serializing object state and sending it to the server is something literally nobody does in a multiplayer game, because then any client can cheat and send ridiculous states.

Volguus
Mar 3, 2009

Suspicious Dish posted:

uhhh just so you know, serializing object state and sending it to the server is something literally nobody does in a multiplayer game, because then any client can cheat and send ridiculous states.

Except that this is what happens almost everywhere. And yes, this is how people cheat. And yes, then programmers add watchers and cheating-detection systems and everything becomes a bit more secure and 1000x more complicated.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
ok i guess i mean when it's not amateur hour. basically, the fancy not-quite-oop serialization system you used for netcode literally doesnt help your game

nonetheless avoiding oop in a video game is a good idea and i'm happy you are experimenting with it. entity-component-architecture has been standard in games for 10 years at this point though.

boo_radley
Dec 30, 2005

Politeness costs nothing

Volguus posted:

Except that this is what happens almost everywhere. And yes, this is how people cheat. And yes, then programmers add watchers and cheating-detection systems and everything becomes a bit more secure and 1000x more complicated.

This kind of depends on the game, right? MMOs use a pattern similar to message queuing and eventual consistency to help prevent or at least identify cheaters if I remember right.

...

Having talked with friends in the game dev works, I'd rather stick with fintech. The requirements are clearer and even for very real time distributed systems I think you've got better wiggle room with latencies and client interactions.

Plus your customers don't tend to be antagonistic fuckbags who will turn on you at the drop of a hat.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
https://medium.com/netscape/async-iterators-these-promises-are-killing-my-performance-4767df03d85b

If you ever find yourself happy that you've managed to make some code only twice as slow as the (much simpler) equivalent code in Python, something has gone very deeply wrong.

vOv
Feb 8, 2014

Plorkyeran posted:

https://medium.com/netscape/async-iterators-these-promises-are-killing-my-performance-4767df03d85b

If you ever find yourself happy that you've managed to make some code only twice as slow as the (much simpler) equivalent code in Python, something has gone very deeply wrong.

The author appears to think that synchronous code must necessarily read the entire file into memory so I don't know if I'd trust his opinions.

Adbot
ADBOT LOVES YOU

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe

vOv posted:

The author appears to think that synchronous code must necessarily read the entire file into memory so I don't know if I'd trust his opinions.

That might very well be the case in Javascript. I'm not familiar enough with the language to say for sure, but in the absence of generator functions or similar, you need something that you can iterate over that comes from a single expression that is evaluated once.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply