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
LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
(I apologize for the length of this post, but you really have to see this in all its glory.)


Ladies and gentlemen, I give you The Invoice Print File Join Method.


It starts out reasonable enough. There are 15 checkboxes that determine what types of invoices to print. Therefore there could be up to 15 files that have already been written to disk. So obviously we need 15 StreamReaders and 15 ArrayLists.
code:
            (initialization code snipped)
            StreamReader sr1;
            StreamReader sr2;
            StreamReader sr3;
            StreamReader sr4;
            StreamReader sr5;
            StreamReader sr6;
            StreamReader sr7;
            StreamReader sr8;
            StreamReader sr9;
            StreamReader sr10;
            StreamReader sr11;
            StreamReader sr12;
            StreamReader sr13;
            StreamReader sr14;
            StreamReader sr15;
            bool first = true;
            bool isHeader;
            string sLine;
            ArrayList alFile1 = new ArrayList();
            ArrayList alFile2 = new ArrayList();
            ArrayList alFile3 = new ArrayList();
            ArrayList alFile4 = new ArrayList();
            ArrayList alFile5 = new ArrayList();
            ArrayList alFile6 = new ArrayList();
            ArrayList alFile7 = new ArrayList();
            ArrayList alFile8 = new ArrayList();
            ArrayList alFile9 = new ArrayList();
            ArrayList alFile10 = new ArrayList();
            ArrayList alFile11 = new ArrayList();
            ArrayList alFile12 = new ArrayList();
            ArrayList alFile13 = new ArrayList();
            ArrayList alFile14 = new ArrayList();
            ArrayList alFile15 = new ArrayList();
Now we have to go through each file and add each line, unless it's a header. "PrintFiles" and "Headers" are variables defined on the local object, which is fortunately a form object! That way you don't have to look too far to find out what actually happens when the user press the button on the form.
code:
            int iCount = 0;
            foreach (string file in PrintFiles)
            {
                iCount++;
                if (iCount == 1)
                {
                    if (file != null)
                    {
                        sr1 = FileUtils.OpenFileRead(file, encoding);
                        while (sr1.Peek() != -1)
                        {
                            sLine = sr1.ReadLine();
                            isHeader = Headers.Contains(sLine);
                            if (first || !isHeader)
                            {
                                alFile1.Add(sLine);
                                first = false;
                            }
                        }
                        sr1.Close();
                    }
                }
                if (iCount == 2)
                {
                    if (file != null)
                    {
                        sr2 = FileUtils.OpenFileRead(file, encoding);
                        while (sr2.Peek() != -1)
                        {
                            sLine = sr2.ReadLine();
                            isHeader = Headers.Contains(sLine);
                            if (first || !isHeader)
                            {
                                alFile2.Add(sLine);
                                first = false;
                            }
                        }
                        sr2.Close();
                    }
                }
                ... (you get the picture)
This is where it gets good. You see, we now have to sort the lines!
code:
            ArrayList alSortFile = new ArrayList();
            int iChoosen = 0;
            int iFile1 = 0;
            int iFile2 = 0;
            int iFile3 = 0;
            int iFile4 = 0;
            int iFile5 = 0;
            int iFile6 = 0;
            int iFile7 = 0;
            int iFile8 = 0;
            int iFile9 = 0;
            int iFile10 = 0;
            int iFile11 = 0;
            int iFile12 = 0;
            int iFile13 = 0;
            int iFile14 = 0;
            int iFile15 = 0;
            while ((alFile1.Count >= iFile1 || iFile1 == 0) &&
                (alFile2.Count >= iFile2 || iFile2 == 0) &&
                (alFile3.Count >= iFile3 || iFile3 == 0) &&
                (alFile4.Count >= iFile4 || iFile4 == 0) &&
                (alFile5.Count >= iFile5 || iFile5 == 0) &&
                (alFile6.Count >= iFile6 || iFile6 == 0) &&
                (alFile7.Count >= iFile7 || iFile7 == 0) &&
                (alFile8.Count >= iFile8 || iFile8 == 0) &&
                (alFile9.Count >= iFile9 || iFile9 == 0) &&
                (alFile10.Count >= iFile10 || iFile10 == 0) &&
                (alFile11.Count >= iFile11 || iFile11 == 0) &&
                (alFile12.Count >= iFile12 || iFile12 == 0) &&
                (alFile13.Count >= iFile13 || iFile13 == 0) &&
                (alFile14.Count >= iFile14 || iFile14 == 0) &&
                (alFile15.Count >= iFile15 || iFile15 == 0))
            {
Everything that follows lies inside this while-loop.

The following code ensues for each file, i.e. 15 times:
code:
                if (alFile1.Count > 0 && iFile1 <= alFile1.Count && (iChoosen == 0 || iChoosen == 1))
                {
                    if (iFile1 < alFile1.Count)
                    {
                        string[] values1 = alFile1[iFile1].ToString().Split(';');
                        if (alSortFile.Count < 1)
                        {
                            alSortFile.Add(StringUtils.Format("{0,6}{1,6}{2,6}{3,6}",
                                StringUtils.IsEmpty(values1[63].ToString()) ? " " : values1[63].ToString(),
                                StringUtils.IsEmpty(values1[65].ToString()) ? " " : values1[65].ToString(),
                                StringUtils.IsEmpty(values1[64].ToString()) ? " " : values1[64].ToString(),
                                StringUtils.IsEmpty(values1[43].ToString()) ? " " : values1[43].ToString()));
                        }
                        else
                        {
                            alSortFile[0] = StringUtils.Format("{0,6}{1,6}{2,6}{3,6}",
                                StringUtils.IsEmpty(values1[63].ToString()) ? " " : values1[63].ToString(),
                                StringUtils.IsEmpty(values1[65].ToString()) ? " " : values1[65].ToString(),
                                StringUtils.IsEmpty(values1[64].ToString()) ? " " : values1[64].ToString(),
                                StringUtils.IsEmpty(values1[43].ToString()) ? " " : values1[43].ToString());
                        }
                    }
                    else
                    {
                        if (alSortFile.Count < 1)
                        {
                            alSortFile.Add(string.Empty);
                        }
                        else
                        {
                            alSortFile[0] = string.Empty;
                        }
                    }
                }
As far as I can tell the contents of this if-statement are 100% identical for each file except for the variable names and such. Don't even ask me what the significance of 63, 65, 64 and 43 is.

Now we have to find the iChoosen file:
code:
                iChoosen = 0;
                iChoosen = SortFiles(alSortFile,
                    (alFile1.Count > 0 && iFile1 < alFile1.Count) ? alFile1[iFile1].ToString() : string.Empty,
                    (alFile2.Count > 0 && iFile2 < alFile2.Count) ? alFile2[iFile2].ToString() : string.Empty,
                    (alFile3.Count > 0 && iFile3 < alFile3.Count) ? alFile3[iFile3].ToString() : string.Empty,
                    (alFile4.Count > 0 && iFile4 < alFile4.Count) ? alFile4[iFile4].ToString() : string.Empty,
                    (alFile5.Count > 0 && iFile5 < alFile5.Count) ? alFile5[iFile5].ToString() : string.Empty,
                    (alFile6.Count > 0 && iFile6 < alFile6.Count) ? alFile6[iFile6].ToString() : string.Empty,
                    (alFile7.Count > 0 && iFile7 < alFile7.Count) ? alFile7[iFile7].ToString() : string.Empty,
                    (alFile8.Count > 0 && iFile8 < alFile8.Count) ? alFile8[iFile8].ToString() : string.Empty,
                    (alFile9.Count > 0 && iFile9 < alFile9.Count) ? alFile9[iFile9].ToString() : string.Empty,
                    (alFile10.Count > 0 && iFile10 < alFile10.Count) ? alFile10[iFile10].ToString() : string.Empty,
                    (alFile11.Count > 0 && iFile11 < alFile11.Count) ? alFile11[iFile11].ToString() : string.Empty,
                    (alFile12.Count > 0 && iFile12 < alFile12.Count) ? alFile12[iFile12].ToString() : string.Empty,
                    (alFile13.Count > 0 && iFile13 < alFile13.Count) ? alFile13[iFile13].ToString() : string.Empty,
                    (alFile14.Count > 0 && iFile14 < alFile14.Count) ? alFile14[iFile14].ToString() : string.Empty,
                    (alFile15.Count > 0 && iFile15 < alFile15.Count) ? alFile15[iFile15].ToString() : string.Empty, sw, iChoosen);
I won't show you what "SortFiles" does, but I can assure you that it doesn't sort any files!

We round things off with a nice, simple if-else chain.
code:
                if (iChoosen == 1)
                {
                    iFile1++;
                }
                else if (iChoosen == 2)
                {
                    iFile2++;
                }
                else if (iChoosen == 3)
                {
                    iFile3++;
                }
                else if (iChoosen == 4)
                {
                    iFile4++;
                }
                else if (iChoosen == 5)
                {
                    iFile5++;
                }
                else if (iChoosen == 6)
                {
                    iFile6++;
                }
                else if (iChoosen == 7)
                {
                    iFile7++;
                }
                else if (iChoosen == 8)
                {
                    iFile8++;
                }
                else if (iChoosen == 9)
                {
                    iFile9++;
                }
                else if (iChoosen == 10)
                {
                    iFile10++;
                }
                else if (iChoosen == 11)
                {
                    iFile11++;
                }
                else if (iChoosen == 12)
                {
                    iFile12++;
                }
                else if (iChoosen == 13)
                {
                    iFile13++;
                }
                else if (iChoosen == 14)
                {
                    iFile14++;
                }
                else if (iChoosen == 15)
                {
                    iFile15++;
                }
Let's hope we have to add another checkbox at some point, so we can take advantage of the flexibility of the code!

Adbot
ADBOT LOVES YOU

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

xf86enodev posted:

The official library reference suggests the use of constants or magic numbers is correct, so I guess Mark just wanted to save bandwidth.

He was probably referring to the use of 2 instead of os.SEEK_END. The python.org example only uses a magic number for the number of bytes to read, not for the seek mode. The number 128 in the Dive Into Python example is also something that could be put in a constant like MP3_TAG_SIZE or whatever, but that isn't a constant you can expect Python itself to know about.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Vaguely on the subject of "input" in Python: One time a coworker of mine wrote code that essentially did this:

code:
def awesome_function():
    if something():
        input = do_a_thing()

    ...

    if input:
        <code that always gets executed because input never evaluates to false>

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Lysidas posted:

What are you talking about?

That wasn't very clear, sorry. Yes, I'm referring to the fact that input always exists because it's a built-in, and do_a_thing() should've been called function_that_never_returns_false().

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

tef posted:

python

is can be chained along with in :q:

Python operators are kind of weird in general (I think they changed this behavior for Python 3):
code:
>>> None < False == 0 < True == 1 < {} < [] < '' < '0' < ()
True
Why is the empty tuple so big?

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

The Gripper posted:

Why is this? It's almost like the parenthesis changes it from a value of True to a reference to True. Similar weirdness with:
code:
>>> 55555 is 55555
True
>>> 55554+1 is 55555
False
>>> 1+1 is 2
True
(I know this is a misuse of 'is', but I expected the same behavior in the 55554+1 line as with the 1+1.)

code:
>>> 255+1 is 256
True

>>> 256+1 is 257
False
...that's interesting.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

ToxicFrog posted:

Here's the bit that confuses me:
code:
>>> 2 > (1 is True)
True
Wait, what?

code:
>>> 1 is True
False
>>> 2 > False
True
Is False getting coerced to 0 there or something?

Yes, False == 0. I'll repeat myself from the previous page:
code:
>>> None < False == 0 < True == 1 < {} < [] < '' < '0' < ()
True
You can compare all sorts of stuff, and not all of it makes sense. Sets Tuples are greater than strings are greater than lists are greater than dictionaries are greater than numbers. 1 is True and 0 is False. None is the smallest thing there is.

LOOK I AM A TURTLE fucked around with this message at 07:15 on Jan 20, 2012

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Doh004 posted:

Found this today while trying to determine a specific sector in some other team's solution:

code:
code with long lovely line
Yes that's all one line, and yes this is repeated in multiple locations :saddowns:

I blame stuff like this partly on the relative difficulty of doing little ad-hoc checks for membership in some constant list in C#. In Python, even your average terrible programmer can figure out how to do this:
Python code:
int(DataContext.Params["pageCode"]) in [1000, 1037, etc.]
What's the best way to write that same line in C#? Like this?
C# code:
new int[] { 1000, 1037, etc. }.Contains(int.Parse(DataContext.Params["pageCode"]))
Not to say the Python example is good either, since obviously there should at the very least be a "ValidPageCodes" list and a function call to wrap the check, but at least it would be easy to tell what the actual codes are at a glance.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

epswing posted:

Correct me if I'm wrong but the codes should be in a hash-based container like a Set or a Dictionary, making the 'contains' lookup O(1) instead of O(n).

Then again, even in the horror example there are only 25 items in the list (I counted :v:), so it's not much of an optimization.

You're not wrong, although I'm sure you'd only feel the difference if you were executing the function many, many times per second.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
In fairness, you are their first ever account.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
God drat do I hate "single point of exit" as a design philosophy. It's the cause of conditional blocks the size of skyscrapers that are impossible to parse when all you need is if (gently caress == null) return false;

Granted, this only happens if the code is also full of massive functions. It's probably okay to use single point of exit if you manage to keep functions small, and it's probably (somewhat) okay to make a lot of long functions if you can make them readable, but combine single point of exit with behemoth functions and you have planted the seeds of despair.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

xf86enodev posted:

Posting C/C++ code should just crash your browser.
Posting Java would be fine though. But it will crash browsers trying to look at the post unless they have signed up to Oracle's Open Post Streaming Intellisense (Enterprise Edition).

In the future, probations will be automatically handed out for posts that don't follow PEP8.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

carry on then posted:

Now I want to write a language where a side effect of the addition operator is that a file on your hard drive is chosen at random and deleted. Just to see what apologists would come up with.

No one is forcing you to use the addition operator. Instead of 1 + 2 you can simply do 1 - -2 instead.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Deus Rex posted:

ignoring the other issues, I don't think it's a big deal to iterate over an associative array like that even if the keys will never be used in the loop body. better to make it obvious to later maintainers that the array is associative than to go for the most brevity, IMO

Aren't PHP "arrays" always associative?

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
I don't think I've ever manually built XML like that, unless you count HTML. But recently I ported (from VB6 to C#) a part of an application that manually generates a particular type of EDI files, and I didn't change the approach at all. :shepface: My code is therefore full of crap like this:

C# code:
string formattedNetProfit = netProfit.ToString("0.00", CultureInfo.CurrentCulture);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("MOA"); // Monetary amount.
stringBuilder.Append(EDIElementDelimiter);
stringBuilder.Append("203"); // Code for item article line after deductions/additions.
stringBuilder.Append(EDIElementPartDelimiter);
stringBuilder.Append(formattedNetProfit); // The amount.
stringBuilder.Append(EDILineDelimiter);
string netProfitSection = stringBuilder.ToString();

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

pigdog posted:

Same thing for anything code-related. It makes better sense to offer the beginners concrete and hard rules, which they may grow out of, rather than trying to explain the intrinsics of electricity to a 2-year-old.

There are a lot more 2-year-olds doing programming than electrical work, though.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

bobthecheese posted:

php:
<?
function dieGeneric() {
    die();
}

// ... some code ...

function suicide() {
    die();
}

// then in another file which is always included
function tantrum($message) {
    die();
}
?>
I suppose that the idea is that they would build in certain generic messages or something... but they never did it.

These aren't the only ones in the project, either, and most of them are used somewhere.

This sounds not so much like a horror as a sadly neglected coding masterstroke.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
The way it pulls the proj_agg_duration function dynamically from the "magic_stats" module is needlessly complex if the pasted code is all there's to it, but when I look at it it makes me think there probably is or has been some alternative way for the "magic_stats" module to be loaded from somewhere else depending on some branching logic further up. If the developer straight up doesn't know that you can do magic_stats.proj_agg_duration(...) then yeah, that's a horror.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
We had a bug in our Easter function recently. It didn't work too well if you gave it 0 as input. (Not really a horror or anything. The bug was just that 0 was being passed in the first place.) But our stupid Hungarian notation, which is ugly on the best of days, is particularly foul here.
C# code:
public static DateTime Easter(int iYear)
{
	int iG = iYear % 19 + 1;
	int iC = iYear / 100 + 1;
	int iX = (3 * iC) / 4 -12;
	int iZ = (8 * iC + 5) / 25 - 5;
	int iD = (5 * iYear) / 4 - iX - 10;
	int iE = (11 * iG + 20 + iZ - iX) % 30;

	if ((iE == 30) && ((iG > 11) || (iE == 24)))
	{
		iE += 1;
	}
	int iDay = 44 - iE;
	if (iDay < 21)
	{
		iDay += 30;
	}
	iDay += (7 - (iD + iDay) % 7);
	return new DateTime(iYear, iDay > 31 ? 4 : 3, iDay > 31 ? iDay - 31 : iDay);
}

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Not sure what the problem is here, flase and treu are perfectly valid synonyms for false and true.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Rothon posted:

The *Impl "pattern" is also used in Java to help out with unit testing. The *Impl class isn't actually the only implementation: tests define mock implementations and use those to avoid dependencies on other parts of the application. You need the interface because the mock libraries use java.lang.reflect.Proxy under the hood which can only implement interfaces, not extend classes.

It's the same with .NET. For instance, the popular mocking library Moq can only mock interfaces and virtual methods on non-sealed classes, because it uses the proxy library Castle DynamicProxy, which has that same limitation. I know that TypeMock's Isolator and Microsoft's own Fakes framework can mock almost anything, but they cost a lot of money. I hate making 1-to-1 class/interface pairs where the odds that I'll ever need to make a second implementation of the interface are basically zero, but the alternative is to make every public method on the class virtual, which is no better, and which is more likely to be forgotten if new methods are added, and also leads to more complexity in the mocking code. And of course every interface will be named stuff like IClassName, since that's exactly what they are. It's got nothing to do with "programming by interface", really; it's purely a technique for mocking. But it's very annoying to have to do it.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Suspicious Dish posted:

Why do they think changing for-loops to while-loops will do anything?

I'm also curious to learn what they mean by "and so forth" in that same parenthetical. Should we also be changing if-statements to gotos?

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
What's the most indented line of code you've ever seen? I've got one that's 19 levels deep, which with 4 spaces per tab means that the line in question begins at column 77. I don't really care about the old 79-chars-per-line rule when doing C#, but you know something is wrong when you're practically already there before you've even written anything.

I won't show the actual method since it's 777 lines long, but here's what the hierarchy looks like:
code:
namespace
    class
        method
            foreach
                try
                    foreach
                        try
                            if
                                if
                                    else
                                        else
                                            if
                                                else
                                                    if
                                                        else
                                                            if
                                                                if
                                                                    if
                                                                        while
I'll show you the last part with the while loop, since it's quite precious:
C# code:
EditionCollection ec = newProduct.Frequency.GetEditions(); // (Comment added by me: EditionCollection inherits from ArrayList)
if (ec.Count < newProduct.NumberOfEditions)
{
    int iEditions = ec.Count;
    while (iEditions > newProduct.NumberOfEditions)
    {
        ec.RemoveAt(0);
        iEditions = ec.Count;
    }
}
ArrayList.RemoveAt is O(n), and RemoveAt(0) is presumably always the worst case since every other element needs to be shifted. Also, while writing this post I've spotted that the while loop will never actually be entered, since ec.Count has to be both smaller than and bigger than newProduct.NumberOfEditions.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Ithaqua posted:

That's silly, especially if you're using MStest when you can just decorate the test method with [ExpectedException(typeof(SomeException))]

The problem with ExpectedException is that you can't distinguish between an exception in your test code and an exception in the code under test. You can end up with tests that pass even though they never even get to the actual test part of the test, because your test setup happens to throw the same exception that you were asserting on. Okay, it's not particularly likely, but the day it happens to you you'll be none the wiser. I also view it as a bad thing that asserting on exceptions is so structurally different from asserting on values, which is why I always use this little snippet instead of ExpectedException:
C# code:
public static void AssertThrows<T>(Action action) where T : Exception
{
    try
    {
        action.Invoke();
        Assert.Fail("Exception of type {0} should've been thrown", typeof(T));
    }
    catch (T exception)
    {
        // You could drop this line if you're okay with matching subclasses of exceptions, or you could add a parameter like "bool allowSubclasses"
        Assert.IsInstanceOfType(exception, typeof(T));
    }
}
You call it like this (although you'll probably want to put it in a utility class somewhere):
C# code:
AssertThrows<MyExpectedException>(() => ThingUnderTest());
Edit: woops, I thought I was in the .NET thread. Nevermind.

LOOK I AM A TURTLE fucked around with this message at 11:09 on Jul 12, 2013

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Crosscontaminant posted:

I wrote this. I'm sorry.

code:
mod = {k: v for k, v in zip(range(-6, 7), map(operator.truediv, map(lambda x: 2 if x < 1 else x + 2, range(-6, 7)), map(lambda x: 2 if x < 1 else x + 2, range(6, -7, -1))))}

Python code:
from __future__ import division
mod = {k: v for k, v in ((x, (2 if x < 1 else x+2) / (2 if -x < 1 else -x+2)) for x in range(-6, 7))}

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

nielsm posted:

Python code:
mod = {x: (max(0, x) + 2.0) / (max(0, -x) + 2.0) for x in range(-6, 7)}

You win this round, nielsm.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Protocol7 posted:

Contrary to popular belief:

code:
Assert.IsTrue(true);
This is not a valuable unit test. I don't think this guy gets the point of unit tests.

(There were just under 6 dozen of these in the last check-in. :negative:)

Possible explanations:
1. "I was going to fill it in later."
2. "I couldn't figure out what to assert on."
3. "It's better than nothing."

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Eric Lippert, one of the designers of C#, has mentioned on many occasions that he regrets that Nullable<T> can only be applied to value types, as opposed to all types. He has also confirmed that the reason is basically that the features -- i.e. 1. Nullable types and 2. The distinction between reference types and value types -- entered the language in the wrong order. From a theoretical point of view the biggest problem is that it prevents the Nullable<T> type from being truly monadic, since you can't have a Nullable<Nullable<T>>. This series of posts touches on it: http://ericlippert.com/category/monads/

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Maybe at first he used a list, then someone told him he should use a hashtable instead, and, well...

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

SavageMessiah posted:

All this is moot on ~*Oracle*~ because '' IS NULL there...

I've actually come to appreciate this about Oracle. 9 out of 10 times the distinction between null and '' is of no interest to my business logic anyway, so I like not having to worry about which one I put in the database. The only thing I hate is when I forget that col = '' doesn't work (you have to do col IS NULL). Even '' = '' returns false.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

The Laplace Demon posted:

The code in all it's glory.
At least it's not Fortran? :suicide:

Leaving aside the quadruple pointer, the most infuriating thing about this is the attitude of "hey guys my code don't work! here it is whats wrong?"

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
I don't know, guys. Doubling my balance sounds like a great idea!

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Howmuch posted:

I'm working on a big project at work and noticed a variation of this being used in the code in multiple places.

code:
lblTimeStamp.Text = timeService.GetCurrentTime().ToString();
Here's the magical timeService.

code:
interface ITimeNow
    {
        DateTime GetCurrentTime();
    }

    public class CurrentTimeService : ITimeNow
    {
        public DateTime GetCurrentTime()
        {
            return DateTime.Now;
        }
    }
:downs:

This is probably being done to facilitate unit testing. I think it's usually overkill, personally, but there are cases where it makes sense. Suppose for example that you have a method with a test like if (DateTime.Today.DayOfWeek == DayOfWeek.Monday) { ... }. How would you write a unit test for that if you can't override the value of DateTime.Today? Run it only on Mondays? There are a number of ways to deal with this issue, one of which is to hide DateTime.Now behind an interface and inject a mocked implementation in unit tests.

Now, if they're doing this but there are no actual unit tests to take advantage of it, then that's certainly the worst of both worlds.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Howmuch posted:

Nope.

Hopefully it was made with unit testing in mind but in comparison with the rest of code from this person I seriously have my doubts.

Like the ~1800 line class on the DAL layer whose only purpose is to enable CRUD for one table in the database.

Probably a cargo cult thing, then. Or an "I'll definitely write tests for this. Later." thing.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Let me see if I understand this. (.) . (.) takes a function that's missing exactly two parameters and composes it with another function that expects the return type of the first function as its first input parameter. Is that right?
code:
let boobs = (.) . (.)
let subtract x y = x-y
let double x = x*2
let subtractAndDouble = double `boobs` subtract
I need to use the boobs operator because double . subtract doesn't type check. It works if there's only one missing parameter to the second function:
code:
let subtractFromFive x = 5-x
let double x = x*2
let subtractFromFiveAndDouble = double . subtractFromFive
And triple boobs lets me do the same thing when there are exactly three missing parameters?
code:
let totalRecall = (.) . (.) . (.)
let multiSubtract x y z = x-y-z
let double x = x*2
let multiSubtractAndDouble = double `totalRecall` multiSubtract
I like pointfree style and all, but this is pretty ridiculous. Can Haskell programmers actually read this stuff? And why is there no Haskell thread?

AlsoD posted:

Somebody learnt to program in Forth clearly :v:

e: alternatively, this is slightly shorter way clearer!
code:
runFunNoTrace = ((fst .) .) . runFun

That is... not clearer to me.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Bongo Bill posted:

There are even fewer men in computers than women because men are larger.

Men in computers tend to be even larger than average. Makes you think.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Verloc posted:

After diving a little deeper, I've come to the conclusion that about 1/3 of the silent catches are legit poo poo-that-should-be-caught stuff. The rest seem to mostly be a byproduct of the original author not really getting how nullables work. About 190 of those catches are basically flow control statements as written by a moron. Instead of null-checking any nullable value that he passes into code that will eat poo poo spectacularly if handed a null(formatted datetimes, ternary operators, string splits, property accessors, etc. etc.), everything is just wrapped in try/catch blocks and if said null intolerant code gets a null and buttfucks itself out of existence, just keep on' truckin'. I'm still grappling with the fact that almost a hundred silent catches on legit exceptions qualifies as 'a drastic improvement over what I initially assessed' however.

That's awful. It's a painful thing to do, but you could consider replacing them with try { ... } catch (NullReferenceException) { }, so at least they only catch what they're supposed to catch. Clearly it would be better to make sure the exceptions don't happen to begin with, but from the sound of it that's going to be a challenge.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

rjmccall posted:

I did describe it as the end point of a long series of questionable decisions. I will happily concede that the chief mistake is making an expression-language. Making an imperative expression language with braces and semicolons is just a refinement of that mistake.

I haven't heard the term "expression language" used in this sense before. Are you referring to languages that have only expression and no statements? Or languages where every code unit has to return a value? "Imperative expression language" is an oxymoron to my uniformed self.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
"Modify" for an operation that actually returns a modified copy instead of mutating the original object is slightly weird, but is somewhat reasonable when it's used in the context of a guaranteed immutable object. Mutation and modification are not the same thing. I'm also inclined to buy the explanation about compatibility with the old API. With all this in mind, I'm going to give PHP as pass on thi

Sedro posted:

Except sometimes it returns false
oh

Adbot
ADBOT LOVES YOU

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Would -Why explain the reasoning and justification behind obscure pieces of code? If it does I'd like to apply it to this if-statement (named changed slightly):

C# code:
if ((module == null && configGroup == null) ||
	(module == null && configGroup.ConfigurationGroupId ==
	config.ConfigurationGroup.ConfigurationGroupId) ||
	(configGroup == null && config.Module != null && module.ModuleId == config.Module.ModuleId) || 
	(configGroup == null && config.Module == null) ||
	(configGroup!= null && module!= null && config.Module != null && 
	configGroup.ConfigurationGroupId == config.ConfigurationGroup.ConfigurationGroupId &&
	module.ModuleId == config.Module.ModuleId) ||
	(configGroup!= null && module!= null && config.Module == null && 
	configGroup.ConfigurationGroupId == config.ConfigurationGroup.ConfigurationGroupId))
{
    // Do something.
}

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