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
NihilCredo
Jun 6, 2011

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

GrumpyDoctor posted:

I've been looking at this for five minutes and I still can't figure out what's supposed to be horrific about it.

Style and structure aside, try that algorithm on 29.

Adbot
ADBOT LOVES YOU

NihilCredo
Jun 6, 2011

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

qntm posted:

I think all of this can be flipped on its head. Code isn't useful unless it's in use. Code that isn't in use can't be maintained, doesn't get maintained, undergoes attrition and becomes progressively less useful. Very quickly it becomes a misleading signpost, worse than useless. New people come in and have no idea why the code has been commented out, what purpose it served, or under what circumstances it would ever be commented back in again. It never gets resurrected and just takes up space.

If there's important code which coders need to see, but which shouldn't actually be in the codebase, then the correct location for that code is in documentation.

I think this is the key point here. I have left commented code in a couple of times, but it was something like this:

code:
/* 
We used to do this with [some software / hardware]. We've since switched over to [other software / hardware]
because of [reasons], but in case we need to return to the older system, here's how it worked:

{code}

/*

NihilCredo
Jun 6, 2011

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

Hughlander posted:

Disagree, that's documentation not code. It should be with the technical design documents ending with "See commit XXXXX for how the code was when it was removed." Block comments explaining the long long ago don't belong in the current code base.

I disagree about sticking it in the documentation, for much the same reason that I wouldn't just leave it to VC history: because I'm assuming that the future developer will not intentionally go looking for it, so it's safest to leave a reference where he will definitely have to look on his way to work.

But I think you are entirely right that I should have written "See commit XXXXX" instead of copying the code block outright. That would have ensured the old code would be seen in context (though if a dude were to uncomment it and find out it doesn't compile anymore, I hope that then he would know to go search through the documentation / version control).

NihilCredo
Jun 6, 2011

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

Isn't that pretty much just a lambda, though? :slick:

NihilCredo
Jun 6, 2011

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

quote:

1) You use a 'railway orientated' approach and it ends up bubbling to the top anyway. Depending on the language, you have difficulty tracking it back to the place where it wrong. This is especially a problem in deeply nested systems. I've done something like this in systems built in C# which should avoid throwing exceptions, so they return an Attempt<T> object instead, and sometimes you do wish you had a stack trace at the point it first went wrong.

You want to log or message the point where it went wrong anyway. In your example, if your FetchAddress() method finds that the address hasn't been added yet, you're going to want to show the user something like "Address not found!", and maybe also write in a log file some more specific information such as which particular query failed.

Also, if you've seen the same Railway Oriented Programming slides I have, then you know that you can just return a custom error type and know at the end of the railway where it is exactly that the failure happened, without need for exceptions or stack traces.

NihilCredo fucked around with this message at 12:25 on Jul 5, 2015

NihilCredo
Jun 6, 2011

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

Vanadium posted:

Not having null is great, but if this compiles...


... then your unit type is basically just null anyway (or x is () too).

Option.None is conceptually much the same as null, yes. But the big difference is that every other method in the program can take a Some x as argument and the compiler will automatically guarantee that it won't be fed nulls, ever.

Whereas with nulls, you can never tell apart a variable that has been null-checked from one that hasn't, so you're forced to always null-check all your arguments anyway.

NihilCredo
Jun 6, 2011

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

Vanadium posted:

I'm talking about unit/(), not None here.

Ah, sorry. Yeah, that's a pretty poor pattern matching block; you're supposed to return the same type for every case, so either you return a x on both sides (i.e. for the None case you return a default value for x) or you return a unit on both sides (i.e. for the Some case, you do something with x and return unit). Returning a type that can be either unit or x is indeed just pushing the null-check downstream.

NihilCredo
Jun 6, 2011

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

If you can't come up with anything descriptive about that object - if there's nothing unique about it or its purpose - I'd much rather read

Thing myThing = new Thing ()

than

Thing thing = new Thing ()

because gently caress case sensitivity.

NihilCredo
Jun 6, 2011

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

Plorkyeran posted:

Mocks are frequently a perfect fit for this thread. Mocking everything is a great way to write a whole bunch of super brittle test code that doesn't even do a very good job of ensuring that the real code works correctly.

:whoosh:

e: holy poo poo, there's no :whoosh: smiley yet? Quick, somebody go pay Lowtax $35 for the privilege.

NihilCredo
Jun 6, 2011

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

Tangentially related: why are most languages still case sensitive? Has "String string" ever been anything but a code smell?

NihilCredo
Jun 6, 2011

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

Blotto Skorzany posted:

Saying "still" presupposes that case insensitivity is an improvement and predominantly a feature of newer languages. Neither of these things are true.

Incidentally, the case of "String string" and similar things isn't only related to case sensitivity - namespaces and lookup rules come into play, too. There are probably languages where you can have an instance of data type x which is named x and not have any problems (except confusion).

I didn't mean to imply the latter (I'm aware of OLD-TIMEY LANGUAGES), but I do the former. I have curiously googled arguments for case sensitivity a few times, with poor results - many answers were just historical notes or mild technical obstacles.

The most common actual argument seems to be "we can use case to convey information, such as whether a certain token is a constant or a variable", which is certainly true, but which doesn't require case sensitivity at all. Case sensitivity forces the user to adopt consistent casing, sure, but there's no reason why you should do it instead of leaving it to your coding environment, in the same way that you do with consistent indentation lengths (I hope). If there is a constant called BUTTS, typing "butts" should autocorrect to BUTTS instead of letting you declare a probably confusing homonym.


Hammerite posted:

I'm not sure if this is a subtle troll to get people to spit bile over the implication that they might use a variable-width font. But it does cause me to wonder whether subtle, contextual changes to letter glyphs could enable what you're suggesting while retaining the character grid of a fixed-width font.

If you could directly manipulate font width, stretching them without changing anything else, what you suggest would be certainly be possible, but I suspect that that sort of manipulation would require a lot of painful hacking in your operating system's GUI libraries.

Sticking to regular font size manipulation would avoid that problem, but if the width difference between 10pt and 9pt doesn't match the one between 9pt and 8pt, and I presume it doesn't, then you're boned.

I guess you could avoid both problems with styling, e.g. bold the C in camelCase, but that looks like rear end.

NihilCredo
Jun 6, 2011

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

VikingofRock posted:

I think there's a pretty good argument for not treating globAllocations and globalLocations as the same variable. (example courtesy of this MonocQc post)

That's a great example, which makes a pretty good argument indeed! It just happens to be an argument for case insensitivity.

A case-insensitive language won't let you define globAllocations at all, if globalLocations already exists in the same scope. You'll get a nice big compiler error and squiggly line.

A case-sensitive language, on the contrary, will happily let you define both. And then, if at any point your cheeto-encrusted fingers hit Tab on the wrong autocomplete entry, or your caffeine-reddened eyes miss the tiny case difference, the program will raise no objections and will compile and run just fine (barring a lucky type mismatch error).

NihilCredo
Jun 6, 2011

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


My favourite part is where it returns null instead of an empty array.

NihilCredo
Jun 6, 2011

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

Pavlov posted:

APL got brought up a few pages ago. Apparently it's a convention to use greek letters as variables. I'd like to think that somewhere right now, a programming intern is hearing "No no, that's not a 'w' that an omega."

APL, not even once.

(preempting pedants: yes, that's actually K, an APL derivative)

(that's a text editor if you were wondering)

NihilCredo fucked around with this message at 16:13 on Aug 15, 2015

NihilCredo
Jun 6, 2011

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

comedyblissoption posted:

is it a requirement to only use terse 1-2 character identifiers in APL or is it just an insufferable programming style

It's the latter, although the "style guide" for K explicitly recommends it.

This is how the creator of K likes to write C code. Definitely a thing for this thread. :stonk:

e: you know, it's so TERSE® and EFFICIENT® that I can just quote it:

code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/mman.h>
typedef void V;typedef int I;typedef double F;typedef unsigned char C,*S;typedef long L;
#define O           printf
#define R           return
#define I(a...)     if(a)
#define W(a...)     while(a)

#define A(a...)     {if(!(a))R 0;}
#define Q(x,s)      {if(x)R O("ERROR: %s\n",s),(S)0;}

#define P(x,a...)   {if(x)R a;}
#define N(n,a...)   {I i=0,_i=(n);for(;i<_i;++i){a;}}
#define J(n,a...)   {I j=0,_j=(n);for(;j<_j;++j){a;}}
#define MIN(a,b)    ({typeof(a)_a=(a);typeof(a)_b=(b);_a<_b?_a:_b;})
#define MAX(a,b)    ({typeof(a)_a=(a);typeof(a)_b=(b);_a>_b?_a:_b;})
#define L8          (8==sizeof(L))
__inline S map(L*n,S s){I d=open(s,0);Q(0>d,s)L b[22];R fstat(d,&b),s=mmap(0,*n=b[L8+5],PROT_READ,MAP_PRIVATE,d,0),close(d),s;}

// reassemble(5-25hours 70-300lines)  READ(.5hour) k(1hour) c(1hour) 6lines

// overlap
I f(S s,S t){I a=strlen(s),b=strlen(t),m=0;P(strstr(s,t),b)N(MIN(a,b),I(!memcmp(s+a-i,t,i))m=i)R m;}

// merge
V g(I n,S*b){I m=0,mi=0,mj=1;N(n,J(n,I k=i!=j?f(b[i],b[j]):0;I(m<k)m=k,mi=i,mj=j))  // max(m mi mj)
 S s=b[mi],t=b[mj];b[mi]=strcat(strcpy(malloc(strlen(s)+strlen(t)+1-m),s),t+m),b[mj]=b[n-1],free(s),free(t);}

// run
I main(I n,S*x){L m;S b[20000],s=map(&m,x[1]);A(s)
 n=0;N(m-1,I h;I('{'==s[i])h=i+1;I('}'==s[i])b[n++]=strndup(s+h,i-h))
 W(1<n)g(n--,b);O("%s\n",*b),free(*b);}

NihilCredo fucked around with this message at 13:44 on Aug 16, 2015

NihilCredo
Jun 6, 2011

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

Suspicious Dish posted:

Yeah, I usually write an absolutely confusing function for this.

JavaScript code:
function clamp(v, min, max) {
    return Math.min(max, Math.max(min, v));
}

Same except I call it "bound". Or "Bounded" if it's an extension method.

NihilCredo
Jun 6, 2011

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

piratepilates posted:

Mid is how you get a substring in a string given beginning and end indices in VB6. That's now burned in my brain.

You can use it still today in VB.NET or maybe even C# too.

It's still in VBNet (can use it from other languages by importing Microsoft.VisualBasic) and it's the best thing.

Unlike Substring() it doesn't freak out and throw if the string is too short, it just returns whatever part of the string fell within the given boundaries. For most use cases this will save you a couple of ugly and easily-forgotten calls to Math.Min().

Its only annoyance is that it uses 1-indexing for historical reasons, but it's trivial to make a 0-indexed wrapper (and you can make it an extension method while you're at it).

NihilCredo
Jun 6, 2011

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

fleshweasel posted:

It is not reasonable to return a nullable Boolean as the result of an equality comparison of any two values. Either they are equal or they are not. I'm assuming this is what you're referring to. This is especially bad when you can pass that Boolean? on to a context that wants a Boolean and your program will explode if the answer to the question "are these values equal?" is "Nothing! :downs:"

It's also not reasonable to allow a Nullable<T> to be implicitly unwrapped and provided to a method that consumes a T. C# won't let you do this and VB will. Programmers need to opt in to such unsafe behavior. If you really want an unsafe program then pass in the .Value member to the method.

C# vs. VB fiddles: (I screwed up these examples a few times in haste, sorry.)
https://dotnetfiddle.net/Mk5tMZ
https://dotnetfiddle.net/7ValA0

The C# implementation of equality comparison for nullables, if you're curious:
https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Nullable.cs#L118
There's an implicit conversion from T to Nullable<T> when you compare to a T. The return type is simply a boolean. If both are null, they're equal; if exactly one is null, they're not equal; otherwise, both are present so do the comparison with the unwrapped values.

You are wrong. DotNetFiddle has Option Strict = Off by default.

If you turn on Option Strict, Nullable<T> is handled correctly. Both of the runtime errors you pointed out become compile-time errors:

https://dotnetfiddle.net/GaJdJ8

quote:

Option Strict On disallows implicit conversions from "Boolean?" to "Boolean"

If you can implicitly unwrap a Nullable<T> in your work project, then it most likely has Option Strict Off as well - either the project properties were changed, or That One Coworker® snuck an "Option Strict off" statement on you somewhere (because he couldn't be arsed to put a bunch of DirectCast()s in his brilliant List(Of Object)-based procedure).

Which would explain why you are "constantly discovering" "terrible things" in VB. ;)

NihilCredo fucked around with this message at 20:12 on Sep 1, 2015

NihilCredo
Jun 6, 2011

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

MALE SHOEGAZE posted:

Could there be Boolable or Errorable types instead of Nullable types?

Of course. Nullable is just a structure with a couple of useful methods, there's no compiler magic involved beyond the shorthand SomeType?.

Remember, Nullable isn't the C#/VB version of Maybe/Option. It does jack poo poo to protect you from NullReferenceException; checking someNullable.HasValue is not any more powerful than checking someObject isnot nothing, in fact it's a little less comfortable because you can't use the various shorthands available (If(), ?. etc.).

Its anti-NRE usefulness comes strictly from the fact that it acts as a reminder to do those null checks, and you can have the switch from SomeType? to SomeType as a hint that you hopefully did check for null at least once (but obviously nothing guarantees that the unwrapped value didn't get set to Nothing at a later point, so you will still want to null check anyway).

When it comes to actual compiler-enforced features, Nullable's only power is to let you have a boolean/numeric/date variable whose default/unassigned value can be distinguished from a regular False / 0 / 1st Jan 1 A.D. value.

Getting back to your question, you could make both of the things you describe, or you could make a more general Eitherable<SomeType><SomeOtherType> with little effort. Just define the appropriate Narrowing CType and Widening CType operators so you can implicitly assign values. But again, you won't gain any more type safety than before, you'll just save on some typing by checking x.IsFirstType instead of comparing x.GetType() = GetType(FirstType).

code:
public structure Eitherable(of t1, t2)
		
	private enum etype
		thisoneshouldneverexist
		t1
		t2
	end enum

	private _whichtypewasassigned as etype
	
	private sub new() : end sub 

	private sub new(p1 as t1)
		_whichtypewasassigned = etype.t1
		f1 = p1
	end sub
	
	private sub new(p2 as t2)
		_whichtypewasassigned = etype.t2
		f2 = p2
	end sub

	public readonly property f1 as t1
	public readonly property f2 as t2

	public shared widening operator CType(ByVal p1 As t1) As Eitherable(of t1, t2)
		return new eitherable(of t1, t2)(p1)
	End Operator

	public shared narrowing operator CType(ByVal e As Eitherable(of t1, t2)) As t1
		if _whichtypewasassigned = etype.t1 then return f1 else throw new InvalidCastException("lol guessed wrong")
	End Operator

	'same operators for t2

	public readonly property IsFirstType as boolean
		get
			return _whichtypewasassigned = etype.t1
		end get
	end property
	
	'ditto for t2

	'for the reckless among us
	public readonly property value as object
		get
			select case _whichtypewasassigned
				case etype.t1 : return f1
				case etype.t2 : return f2
				case else: throw new exception("someone hosed up")
			end select
		end get
	end property	
		
end structure

NihilCredo fucked around with this message at 22:14 on Sep 1, 2015

NihilCredo
Jun 6, 2011

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

fleshweasel posted:

Something is wrong in our project settings I guess, because I was sure we had Option Strict On. Is it a project-wide setting, or does it need to be applied in each source file?

Also possible that some projects in our solution have it on while others don't. Actually, that might be exactly what's wrong. At any rate, unsafety by default is the wrong way to design a language.

It's a project-wide setting, but you can override it for an individual file by putting Option Strict [on|off] at the top of the file.

There is also a setting in the Visual Studio options that sets the default value for new VB projects you create.

In any case, as far as awful legacy features VB.Net inherited from VB6, Option Strict and hell even Option Explicit aren't that bad. Since we're in the Coding Horrors thread, everybody go check out the On Error Resume Next statement. Bring vodka.

(If you don't fully grasp why OERN is such a horror, or why I have a don't-try-to-find-out-if-I'm-joking rule at work that anybody who puts that in a commit is fired, consider that the following code:

code:
on error resume next
	
dim foo as string = nothing

if foo.length > 100 then console.writeline("dog") else console.writeline("cat")
prints dog.)

NihilCredo fucked around with this message at 22:30 on Sep 1, 2015

NihilCredo
Jun 6, 2011

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

Soricidus posted:

now try vbscript, where it's literally the only way to handle errors. enjoy trying to predict which operations can cause an error and then manually checking the global error object after every single one! or what everyone actually does, which is leaving it to the next guy to figure out why things suddenly start failing silently five years down the line.

poo poo, it didn't even have On Error Goto? I thought that one at least was alright, since it's pretty much a primitive try/catch block. Other than the whole "no exception object" thing.

fake edit: SO'd it, apparently you're supposed to put dangerous operations into their own OERN-less procedures, which will return immediately on an exception, and you call them from an OERN procedure in which you check the return / global variables immediately after calling one of those dangerous functions. I guess it encouraged proper function splitting at least? :shrug:

NihilCredo
Jun 6, 2011

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

I had two coworkers who used to write that kind of stupid concatenation / indexOf tricks when they needed to store some information as a loose string.

However, that was because they had literally never heard the word "serialisation". Once I showed it to them, their reaction was "oh wow, I can do this stuff with a one-liner from the standard library and it works on any object? awesome!" and they were all too happy to delete their terrible functions.

What I'm saying is, your frontend developer is a terrible person before being a terrible frontend developer.

NihilCredo
Jun 6, 2011

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

McGlockenshire posted:

e: ffs, it came from StackOverflow... look at those tables. LOOK AT THEM.

A hero for our times: that dude who resistd the temptation of showing off his clever coding skills in favour of a sober reminder that no, you need an actual calendar because holidays exist.

NihilCredo
Jun 6, 2011

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

I'm a page late for the brace talk, but my favourite brace placement style is and will always be the Python:

NihilCredo
Jun 6, 2011

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

Jumpingmanjim posted:

We also have a burn down chart that seems to keep burning up and stand up meetings that go on for too long. I wonder if there's enough material for a bad Agile thread.

It could probably double as the Agile General thread anyway.

NihilCredo
Jun 6, 2011

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

Suspicious Dish posted:

I'd be happy if most of my bug reports had stack traces attached. Error reporting is hard when your core product is, by design, not always online.

Oh, there are ways around that, if you're sufficiently... creative.



"Sir, your exception."

NihilCredo
Jun 6, 2011

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

So, I gather that the perfect version of this code should have no mutation, a single return statement, and two braces for every if block.

Well, the solution seems blindingly obvious to me. I don't know, maybe you're all bad? :confused:

code:
    @Override
    public boolean equals(Object o) {
        return ((o == this) || ((o instanceof Coordinate) && ((Coordinate)o.x() == x) && ((Coordinate)o.y() == y)));
    }

NihilCredo
Jun 6, 2011

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

.NET structures are meant for very small dumb data holders or thin wrappers, small enough that it's cheaper to copy them everywhere than to pass a reference. I believe the max recommended size is 16 bytes iirc.

NihilCredo
Jun 6, 2011

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

I think I'll start posting tiny horrors from our production codebase once per day and see how long these ~70k LoCs keep delivering.

Let's start with a classic. How do you check if a Decimal variable is negative?

Answer: If quantity.ToString().Substring(0, 1) = "-" Then ...

NihilCredo
Jun 6, 2011

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

Munkeymon posted:

I pasted https://codepoints.net/U+1F4A9 into Visual Studio the other day and was pretty surprised when it worked.

https://dotnetfiddle.net/qOkMCD

I'd have pasted it but the F# compiler apparently has better Unicode support than the SA forums.



NihilCredo fucked around with this message at 22:25 on Oct 21, 2015

NihilCredo
Jun 6, 2011

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

xzzy posted:

The forums "support" it just fine. You can spam unicode and emoji all you want and it works.

Not inside [ code ] blocks, they use a different font.

💩

code:
&#128169;

NihilCredo
Jun 6, 2011

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

comedyblissoption posted:

Treating enums as integral values means some rear end in a top hat is going to do cutesy integer arithmetic on it or that you'll have to consider cases where you get an integral value that doesn't map to the assigned enum integral values.


Or worse, you could be working with someone who thinks flag enums are really cool and not an abomination :commissar:

NihilCredo
Jun 6, 2011

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

Suspicious Dish posted:

ok, i'll bite: what's wrong with flag enums?

If you're not at the optimisation level where you care about saving bits - you aren't, especially if we're talking about c# - then a struct of bools is better and safer in every single way. It explicitly states its nature and its functioning, it's impossible to define it or operate on it in a broken way, its usage is far more readable, and it's trivial to extend it when necessary (for example, if one of the flags needs to allow for a third value).

Flag enums are a clever efficiency hack, which are the three most damning words I know to describe a programming construct.

NihilCredo
Jun 6, 2011

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

We have Pokemon exception handling at work. Every single method - and I do mean every single one - is structured as

code:
Try
    ' do stuff here
Catch ex As Exception
    WriteLog("ModuleName", "MethodName", "An error happened while fooing the bar!", ex.ToString, showPopUp:=true, {bunch of optional arguments for error level etc.})
    MethodName = 'set return value to a default failure value
End Try
Most of the time it doesn't work too badly. It's boilerplate-y as gently caress, but I have a CodeRush macro to add it automatically and with VB14's NameOf() operator I may be able to get rid of a couple of those arguments without the need for reflection.

The problem happens when you have this:

code:
     For Each product in Products()
          RefreshProduct()
     Next
If there's an exception that happens in RefreshProduct() because of a corrupt db table or whatever, and the showPopUp in RefreshProduct()'s catch block was set to True (because it's a method that normally gets invoked on one article at a time, for example), the user is going to enjoy a nice series of 27000 "There was an error while refreshing a product!" popups.

So every time you write a loop, you have to check the implementation of every function you call and make sure it's "silent", and if it isn't you must add an extra argument to make it avoid any popups.

NihilCredo
Jun 6, 2011

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

Hammerite posted:

Type-safety, primarily. Less error-prone, because the compiler can check that you're invoking the function correctly. The IDE will be better at helping you out (at least, MSVS is hopeless at macros; I assume other IDEs are similarly better at supporting code that doesn't make heavy use of macros, because macro-expansion is hairy to make sense of*). Assuming a reasonable compiler, there should be no difference after compilation, so I don't follow your "optimal code" statement.

* Having "programmed" in TeX in the past, I am very wary of making use of macro expansion when there are better alternatives available.

I share your distaste for macros, but why do they pose a problem for IDEs? If they can run the compiler in the background to type check your code, I don't see why it would be any harder to run the preprocessor followed by the compiler instead.

NihilCredo
Jun 6, 2011

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

jony neuemonic posted:

I also enjoy writing SQL, so maybe I'm the horror after all.

Same here. Any time I write a new feature, I start with "OK, how much of this business logic can I just write as a query/sproc?", because I know it won't break from random code changes and also it's often orders of magnitude faster.

Persistence ignorance sure sounds nice, but in this particular case I think tight coupling offers far more advantages.

NihilCredo
Jun 6, 2011

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

I also get the impression that 3/4ths of the fancy stuff vim users brag about can usually be done just as fast with a regex ("I can type a command to replace all the text between braces!").

And becoming fluent with regex is both easier and far, far more applicable than becoming comfortable with vim.

NihilCredo
Jun 6, 2011

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

I'll take four comparatively cheap 23" 1080p screens over a single 30"-40" 4K screen, personally.

I need lots of screen real estate, but I don't particularly need to have it on the same screen. Having several cheaper screens will provide the same total real estate for the same or probably less money, and will display it in a bigger size = easier on the eyes.

Currently I'm using a 26" screen, a 17" laptop screen, and a 15" touchscreen. It works well enough - IDE / SQL on the main screen, email / browser on the laptop, our program on the touchscreen (it's the smallest size we support). I may end up grabbing another screen from the storage at some point, if I can be bothered to deal with the huge red tape involved*.



* by which I mean "ask the warehouseman if there's any monitors I can grab that won't be needed for a few months". Small companies have generally poo poo pay, but there's some silver linings.

NihilCredo
Jun 6, 2011

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

ratbert90 posted:

Coding horror of the day.

code:
$i = 0;
while($i < 2)
{
    $i = $i + 1;

    DO STUFF
}


Meh, could easily have been worse.
code:
DO STUFF
DO STUFF

Adbot
ADBOT LOVES YOU

NihilCredo
Jun 6, 2011

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

lord funk posted:

We should have a contest for someone to write the horror-est code. I bet it would be hilarious.

Six months ago I would have enjoyed it, nowadays I no longer think I could top Arthur Whitney.

an interview posted:

BC: Do you ever look at your own code and think, "What the hell was I doing here?"

AW: No, I guess I don't.

BC: [..] In terms of debugging your code, obviously the power of a terse language such as K or Q is that, presumably, it's easier to find bugs by inspection. How do you debug them?

AW: In C I never learned to use the debugger so I used to never make mistakes, but now I make mistakes and I just put in a print statement. K is interpreted, so it's a lot easier. If I'm surprised at the value of some local at some point, I can put in a print, and that's really all I do.

NihilCredo fucked around with this message at 22:03 on Nov 18, 2015

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