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
dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
It could also conceivably make cleanup easier, if there's only one point where your code can exit a function, then there's also only one point where you need to de-allocate resources etc.

Of course, now (almost) every language has far better methods for doing this. Not to mention that the very presence of exceptions means you might not be able to rely on your single point of exit (and thus your cleanup) ever executing.

Adbot
ADBOT LOVES YOU

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
C# code:
if (productCountState.FirstOrDefault() != null)
{
    if (productType.URL != null && productType.IsFooProduct && 
            (!productType.FooUpdatesOnly &&
                (
                    state.Code == BlahOrderStates.ACTIVATE.ToString()
                    || state.Code == BlahOrderStates.ACTIVATING.ToString()
                    || state.Code == BlahOrderStates.TERMINATE.ToString()
                    || state.Code == BlahOrderStates.TERMINATING.ToString()
                    || state.Code == BlahOrderStates.UPDATE.ToString()
                    || state.Code == BlahOrderStates.UPDATING.ToString()
                )
            ) ||
            (productType.FooUpdatesOnly &&
                (
                    state.Code == BlahOrderStates.UPDATE.ToString()
                    || state.Code == BlahOrderStates.UPDATING.ToString()
                )
            )
                            
        )
    {
        //code
    }
}
Member names are somewhat altered, but I made sure to preserve the exact formatting.

I honestly don't know which part I hate most.

e:
Also worth mentioning, BlahOrderStates isn't an enum, it's a static class with a bunch of public const strings.

dwazegek fucked around with this message at 14:16 on Nov 28, 2012

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
code:
url = "PhoneNumbers/phonenumberoverview/PhonenUmberSomething"
Inconsistent casing :argh:

and yes is really is PhonenUmber

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
Found about a bazillion instances of this in a ASP.NET MVC3 project
code:
<div>
   @{string SomeButton = "<input id='SomeButton' style='cursor:pointer' type='button' value='Blablabla'/>";
   @Html.Raw(SomeButton)}
</div>

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Gazpacho posted:

Oh, I can just guess:

[Junior dev drops XHTML tag into HTML document]
"Why the gently caress am I getting a warning? Stupid Macro$uck!! They can't do anything right!"
[Dev changes tag to a string echo, saves day]:c00lbutt:

Might've been an intern who initially wrote it like this. But the horror goes a bit deeper than that. The guy who mostly works on this project is definitely not a junior developer, but he does heavily favor the copy-paste style of programming, so, what otherwise might've been a few isolated WTFs, are now repeated dozens or even hundreds of times throughout the code base.

For bonus fun, he seems to have realized the stupidity of the aforementioned code, and fixed it on a few pages.

By "fixed it" I mean he changed it into this:
code:
<div>
   @{string SomeButton = "<input id='SomeButton' style='cursor:pointer' type='button' value='Blablabla'/>";
   @SomeButton }
</div>
Of course this was also pushed to production without testing it, so we just had a bunch of users complaining that their buttons weren't really buttons anymore.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
Definitely not going to touch any of that poo poo unless I have to. If a change or fix requires a decent amount of work on a page, then I'll redo the page, if only because the messed up outlining and complete lack of any structure makes it really hard to find anything.

But the stuff I posted is just the tip of the ice-berg, the real problems are far more serious. Technically it's an MVC web site, but so far, I've hardly seen any use of the "M", instead everything is passed through the ViewBag/ViewData. There's 50+ pages, almost all with dynamic content, but somehow less than 10 Model classes.

The Session is also misused terribly (big surprise), yesterday I found a Controller action that stuck all sorts of stuff in the Session, then called a method, which proceeded to pull that same stuff out of the Session, instead of just simply passing it as method parameters. I fixed that, but because everything is copy-pasted everywhere, I know I can just open up any other Controller and find the exact same crap. Add onto that that everything that's put in the Session is needlessly converted to a string first, so there's a ton of parsing code spread all over the place.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
code:
/// <summary>
/// Exception class for throwing a Blah exception.
/// </summary>
public class BlahException : Exception
{
  /// <summary>
  /// The error message.
  /// </summary>
  public string ErrorMessage { get; private set; }

  /// <summary>
  /// Constructor.
  /// </summary>
  /// <param name="errorMessage"></param>
  public BlahException (string errorMessage)
  {
    ErrorMessage = errorMessage;
  }
}
It's like an actual exception, just less useful.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Cerberus911 posted:

Finally something to contribute.

I can one-up that.

An ASP.NET MVC3 web site I'm working on is littered with this

code:
public ActionResult DoSomething(string SaveMode)
{
  bool saveMode = SaveMode != null && SaveMode == "true" ? true : false; 
  
}
Which is horrible on all sorts of levels.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
code:
for (int i = 1; i <= variableWithNameThatsTooLong.Count / 11; i++)
{
  int? foo = variableWithNameThatsTooLong.Where(le => le.Id == i && le.key == "foo").First().Value == string.Empty ? null
  : (int?)int.Parse(variableWithNameThatsTooLong.Where(le => le.Id == i && le.key == "foo").First().Value.ToString());

  int? bar = variableWithNameThatsTooLong.Where(le => le.Id == i && le.key == "bar").First().Value == string.Empty ? null
     : (int?)int.Parse(variableWithNameThatsTooLong.Where(le => le.Id == i && le.key == "bar").First().Value.ToString());

  int? qux = variableWithNameThatsTooLong.Where(le => le.Id == i && le.key == "qux").First().Value == string.Empty ? null
     : (int?)int.Parse(variableWithNameThatsTooLong.Where(le => le.Id == i && le.key == "qux").First().Value.ToString());

  //some thing repeated 4 more times for different keys

  bool isPublic = bool.Parse(variableWithNameThatsTooLong.Where(le => le.Id == i && le.key == "LeIsPublic").First().Value.ToString() == "false" ? "FALSE" : "TRUE");
  
  //more code
}
I don't know what I hate most about this code.

The guy who wrote this also has an unhealthy obsession with dictionaries, the entire codebase is littered with methods that take Dictionary<string, string>, Dictionary<string, object> or Dictionary<int, object> as parameters. Which is great, because there's no loving way to determine what data I need to give to a method without reading through the code.

Of course, he never uses a dictionary when its use would actually be justified, like loading an entire set of data in one query and storing it in a dictionary for fast lookups, instead he'll just fire off 500 separate database queries.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
During a recent change, we added functionality to allow the user to select whether certain processing steps should be skipped for certain items. Instead of implementing this in any sane way, a parameter of type Dictionary<int, bool> was added to a whole bunch of methods. Each method would then check if the item's id was was present in the dictionary, and if the value associated with it was true.

To reduce some boilerplate code, I mentioned that it might be easier to just pass the ids of items that needed to be skipped, then you'd only need to test if the id was present.

Apparently someone decided to follow my suggestion and this hideous code:
code:
private Dictionary<int, bool> getSkipItems(FormCollection fromCollection)
{
  Dictionary<int, bool> skipItems = fromCollection.AllKeys.Where(k => k.EndsWith("__SkipItem"))
    .ToDictionary(k => int.Parse(k.Split('_')[0]), v => bool.Parse(fromCollection[v].Split(',')[0]));
  return skipItems;
}
was changed to this masterpiece:
code:
private List<int> getSkipItems(FormCollection fromCollection)
{
  Dictionary<int, bool> skipItems = fromCollection.AllKeys.Where(k => k.EndsWith("__SkipItem"))
    .ToDictionary(k => int.Parse(k.Split('_')[0]), v => bool.Parse(fromCollection[v].Split(',')[0]));
  skipItems = skipItems.Where(kvp => kvp.Value == true).ToDictionary(key => key.Key, value => value.Value);
  List<int> keyList = new List<int>(skipItems.Keys);
  return keyList;
}

dwazegek fucked around with this message at 13:48 on Oct 9, 2013

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Jabor posted:

Well, you can enforce at compile-time that a function only accepts parameters with the appropriate marker interface.

Yeah, the last sentence of the explanation of the FxCop rule even mentions this.

There's pros and cons to either way of doing it and it's up to the developer to decide which is best for them. This FxCop rule should only be seen as a reminder that you might want to use an attribute, not as a "X is the wrong way, Y is the right way" type of rule.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
code:
public bool IsNumeric(object numberString)
{
  char[] ca = numberString.ToString().ToCharArray();
  for (int i = 0; i < ca.Length; i++)
  {
    if (!char.IsNumber(ca[i]))
      if (ca[i] != '.')
        return false;
  }
  if (numberString.ToString().Trim() == "")
    return false;
  return true;
}
I guess it's not the worst piece of code in the world, but still...

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
code:
IDictionary<int, Something> types = ....;

//(No need to sort types.Keys because types IDictionary is an instance of type SortedDictionary)
foreach (var key in types.Keys)
{
  var type = types[key];
  ...
}
gently caress you. Doing it the right way would have cost less effort than typing out that horrible excuse for why you're too cool to sort the data.

The clincher is that types is never a SortedDictionary, it's always a (regular) Dictionary.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
If you make the same off-by-one error on both sides of a comparison, is it still an error?

code:

bool isInRange = inner.Start >= outer.Start && inner.Start + inner.Length <= outer.Start + outer.Length;

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Steve French posted:

Looks completely reasonable to me

Yeah, I should've provided more context.

There were a few legitimate off-by-one errors in related code where the (inclusive) upper bounds of the range was repeatedly calculated by doing start+length. I'm pretty sure the same buggy code was copy/pasted when writing this code, but because it's balanced on both sides of the comparison, it works.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

1337JiveTurkey posted:

I have no idea how the ranges are being used but for something like addressing ranges in an array wouldn't inner.Start + inner.Length overflow even though inner.Start + inner.Length - 1 could still be valid?

I can't give any specifics, but there's no danger of overflowing. Both numbers are 32 bit integers, are always positive, and the maximum upper bound is never going to be more than 10 million.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

NFX posted:

code:
void ConvertLFToSpace(char* buff)
{
    unsigned int i;
    for (i = 0; i < strlen(buff); i++) {
        if (buff[i] == '\r') //\r = 10
            buff[i] = 32;
    }

}

void RemoveCRFromStr(char* Value)
{
    int i = 0;
    while (Value[i] != 0) {
        if (Value[i] == '\n')
            Value[i] = 0;
        i++;
    }
}
According to blame, they were written by the same person, at the same time.

All other issues aside, that single comment is absolutely amazing in how much it misses the point.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

pokeyman posted:

Why would you need comments just look at the descriptive function names, it is self-documenting!

Well, based on that code, self-documenting code and comments are both useless, so I guess we should use neither :v:

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
C# code:
string fileName = string.Format("Something_{0}.csv", DateTime.Now.Year.ToString() + "-" + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Day.ToString());

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
C# code:
resultset.All(x => { x.StatusName = getCusTomPriceStateNameByCode(x.CustomPricingStateEnum); return true; });

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Manslaughter posted:

Also, CusTom.

The guy who wrote this is absolutely terrible when it comes to that sort of stuff, there are at least 5 different misspellings of CustomPricing in the entire change. Even in that tiny snippet there's an inconsistency between CustomPricing and CustomPrice.

Other stuff that we're (sometimes permanently) stuck with thanks to him: "GeneRatePassword", "PhoneNumberSerfvice", "PhonenUmberController", "DoProviosing", "ReferenceLonegerThen50".

He's also the only person on the entire team that insists on using lower-case method names for private functions. No big deal, it's just annoying that everyone adheres to a certain standard, and he consistently breaks it. On the plus side, I can tell that the code is going to be terrible before I see it, because I know he wrote it.

edit:
I just realized I started the post with "The guy who wrote this is absolutely terrible when it comes to that sort of stuff...", implying that he's not-terrible at other stuff, which isn't true. He's equally terrible at everything.

dwazegek fucked around with this message at 18:55 on Nov 7, 2014

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Xenoveritas posted:

One more.

Java code:
public static boolean StringLexicographicallyGreaterThan(String S1, String S2) {
    // Returns true if S1 is lexicographically greater than S2 where the codepoint of each character is compared.
    // Returns false otherwise
So, uh, wait, how is this different than S1.compareTo(S2) > 0?

Java code:
    if (S1.length() > S2.length())
        return true;
    if (S1.length() < S2.length())
        return false;
Oh. I see.

What does it return if S1.length() == S2.length()?

On a somewhat similar note, I found this yesterday:
C# code:

private bool nullableDecimalEquals(decimal? d1, decimal? d2)
{
  if (d1 == null && d2 == null)
    return true;
  if (d1 == null)
    return false;
  if (d2 == null)
    return false;
  return d1.Value == d2.Value ? true : false;  
}

In case you're not familiar with .NET nullables, this gives the exact same results as the default equality comparer; I guess writing d1 == d2 was too easy.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
A colleague of mine does something similar. He'll first outline the different steps a method has to do in comments, then write the code. Which, in general is fine, except he leaves all the comments in, and never adds any actually useful comments. So all his code looks like this:
code:

//Create bar for foo
CreateBar(foo);

//Set foo active
SetActive(foo);

It's not the worst thing in the world, but it's utterly pointless, and it's everywhere.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

nielsm posted:

So it's a dictionary for passing stuff into templates? Except not really a dictionary because that would be too easy?

It kinda sorta is a dictionary. The ViewBag and ViewData contain the same data, they just represent 2 different ways of accessing it.

ViewBag acts as a dynamic expando object (it's not only accessed dynamically, but members can also be added and removed at runtime). ViewData acts as a Dictionary<string, object>.

So ultimately the difference is just in how you access it. ViewBag.Something = "whatever" is equivalent to ViewData["Something"] = "whatever" And seeing as they refer to the same data you could do something like this:
code:
ViewBag.Foo = "bar";
ViewData["Foo"] == "bar"; // true
Basically, you just use whichever syntax makes the most sense at the time. Most people seem to prefer the ViewBag syntax, but that only easily allows for adding data and modifying existing data, so if you want to do more complex stuff, you'd use ViewData (although it's probably a horror if you need to do anything of the sort).

Knyteguy posted:

* It might be static instead of instantiated, and perhaps data is flushed every time a view is called? I've never tested.

It's instantiated per request[1] and carries over when rendering the view, and is automatically passed to partial views and display/editor templates when they're rendered. I'm not sure if the data is maintained when calling Html.RenderAction/Html.Action from within a view though.

All that said, strongly type ViewModels are definitely the way to go for most cases. I only use it when I need to pass data between partial views (or templates) and for whatever reason I can't use a model.


[1] Strictly speaking this isn't true, but it's true enough :v:

dwazegek fucked around with this message at 01:29 on Dec 16, 2014

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Brain Candy posted:

People bringing up DI seem to segue into "and you can use it with singletons!!!" pretty quickly. When did global mutable state become okay?

It's not uncommon to end up with a bunch of classes that don't have mutable state, so they can be safely turned into singletons.

Still doesn't make it a good idea to actually do so though.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Hughlander posted:

I've had it strongly argued to me that in almost every case all a DI container is anyway is a singleton through indirection. Wether it's by injecting Singletons, or by getting a Factory Singleton. Of course this was also arguing against any sort of DI for a dynamic scripting language like Ruby...


I guess you could argue that the DI container itself is a singleton, cause there' generally only one per application. I'm not sure why that would be relevant though.

But why would anyone assume it's injecting singletons?

The only times I've ever used singletons in a DI container is for stuff like (immutable) config classes where there only is 1 instance for the entire application. In every other case (including factories) the injected instances have always been tied to some scope, or have been new instances.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
How to miss the point of using StringBuilders:

code:
StringBuilder message = new StringBuilder();

message.AppendLine("Blablabla:");

if (foo.Bars != null)
{
    foreach (var bar in foo.Bars)
    {
        StringBuilder barMsg = new StringBuilder();
                    
        barMsg.AppendLine(bar.Baz + " " + bar.Quz + ": ");

        if (bar.Quux != null)
        {
            foreach (var quux in bar.Quux)
            {
                barMsg.AppendLine("\t" + quux.Garply + " : " + quux.Waldo);
            }
        }

        message.AppendLine(barMsg.ToString());
    }
}

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
I'm not familiar enough with C to determine if this is a horror, but I think it is.

I was browsing the wikipedia page on checkdigits, and under the section for ISBN 10 it says the following:

quote:

The sum can be computed without any multiplications by initializing two variables, t and sum, to 0 and repeatedly performing t = t + digit; sum = sum + t; (which can be expressed in C as sum += t += digit;)

code:
sum += t += digit;
Isn't that undefined behavior in C?

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

nielsm posted:

What might be undefined was if you do something like
sum += sum += digit
since that assigns to sum twice in one sequence element, meaning the order of the assignments would be undefined.

Yeah you're right, this was what I was thinking of. Guess I'm the horror :v:

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

FeloniousDrunk posted:

code:
catch (Exception e){
  e.printStackTrace();
  try{
     this.ct.close();
  }catch (SQLException e) {
     e.printStackTrace();
  }
}finally{
  try{
    this.ct.close();
  }catch (SQLException e) {
     e.printStackTrace();
  }
}

This is beside the point, and I realize that it might be the result of anonymization/simplification you applied.

Is it really possible to catch an Exception e in a catch block that already catches an Exception with the same name in Java?

If so, that seems like a horror to me.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Carefully, and with blind disregard for IPv6.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Munkeymon posted:

.Net decompilation is really good/accurate/reliable/whatver and I doubt there's an obfuscater out there that can take a well-architected program and turn it into a god-class abomination, so I'm going to go with bad design.

If an obfuscater mangled a bunch of smaller classes into some unholy amalgam, then it would also break a ton of stuff that relies on reflection. So yeah, this is definitely bad design.

Maybe in the original source files the class is divided into a bunch of partial classes, which could make working with it manageable, but that doesn't make it less of a horror.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
This was part of a larger function. It's an algorithm to determine how many items are in a block of items. In this case the number of items can only ever be powers of 10 (1, 10, 100, 1000, etc).

C# code:
int length = blockSize.ToString().Length;
int count = (int)Math.Pow((double)10, (double)length - 1);
In order to determine how many items there are, you only need one input parameter, an integer representing the number of items there are. :psyduck:

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Janitor Prime posted:

Yeah, anyone doing it differently is stuck in the stone ages. How do other languages do it?

Depends on the IOC container mostly. E.g. Castle Windsor for .NET can be configured in different ways. AFAIK the 2 default behaviors are to either inject through the constructor (resulting in an exception if a dependency can't be resolved) or injecting through public properties (in which case I think it'll only inject properties of types it knows). For property injection you can also mark a property to always be ignored, and I think you can also either mark the property or configure Castle so that it'll throw on missing dependencies.

However, you can extend/change Castle's behavior in so many ways, that I wouldn't be suprised if you could allow for injecting private fields as well.

For the most part we use constructor injection, and sometimes allow for injecting non-required stuff (mostly loggers) through properties, so you'd have something like this:
C# code:
private readonly ISomeRepository _someRepository;

public SomeService(ISomeRepository someRepository)
{
   _someRepository = someRepository;
   Logger = Logger.NullLogger;
}

public ILogger Logger { get; set; }
So you're guaranteed by Castle to get a valid ISomeRepository, and if an ILogger is configured we'll also get one of those, but if it isn't we'll just default to an ILogger that does nothing.

A slight advantage is also that, when you're writing unit tests, and thus creating an instance of SomeService yourself and mocking dependencies, if someone adds a dependency, it'll be caught compile time, rather than resulting in failed tests due to null references.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
An idiot ex-colleague of mine had the really annoying habit of using bitwise AND or OR when comparing booleans. So (e.g.) he would write this:
C# code:
if (something == 4 | something == 5) { }
Instead of the standard
C# code:
if (something == 4 || something == 5) { }
No matter how many times everyone told him to stop doing that poo poo, he kept on doing it. Now that's enough of an horror, but today I found this EF query (anonymized):

C# code:
var query = from f in Foo
  where f.Code == Something | f.code == SomethingElse
  && f.ParentId == parentId
  && f.IsActive
  select f;
From the context in which this code is used it's clear that the first part of the query should actually be in parentheses, but because there are no parentheses it seemingly evaluates to (f.Code = Something) OR (f.Code = SomethingElse AND f.ParentId = parentId AND f.IsActive = 1)

However, the query builder for EF is smart enough to recognize that bitwise operations have precedence over logical operations, so it turns in into the correct query (f.Code == Something OR f.Code = SomethingElse) AND f.ParentId = parentId AND f.IsActive = 1

So his idiotic habit actually saved him from a bug. That, or the more terrifying alternative that he actually did this on purpose thinking he was smart, which might actually be that case as the ANDs ar all logical ands, whereas he would normally use bitwise ANDs as well.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

TheresaJayne posted:

Also using == instead of .equals

Based on the casing of ToString and ToLower, it's c#, not java, so == is perfectly fine, and in my opinion even preferable.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:
I love how that is-positive-integer module imports a module in order to a logical AND between two boolean expressions. Which in turn imports a number of modules, one of which is a module to do a logical AND between two booleans.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Suspicious Dish posted:

Yeah, but those languages don't have the feature where two number-like strings are parsed to numbers and then tested.

code:
$ php -r 'var_dump("1e3" == "1000");'
bool(true)

Wait doesn't php also have the thing where "12ab" == "12cd"?

So that would mean that "1d3" == "1d4", but "1e3" != "1e4", right? :psyboom:

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

SupSuper posted:

My favorite Go horror story is a Kickstarter game which failed once their programmer left, because nobody else could get the code to even compile anymore. The dependency versions Go pulled had changed from the cached versions the original programmer had, so the codebase was an unusable broken mess.

Between this and a bunch of recent npm stupidity, do people not add their dependencies to source control? :confused:

Adbot
ADBOT LOVES YOU

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

FrantzX posted:

There is no idea so bad that no one hasn't implemented it.

If esoteric language are bad ideas, then I don't want to be right :colbert:

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