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
Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

The Noble Nobbler posted:

Business programming?

"Can we have it in Excel?". Eh, keeps me in a job.

On the topic of regular expressions and 'knowledge requirements', sod the theory, it's just nice if the original developer documents what it's *supposed* to do, and what the expected form of the inputs are.

Adbot
ADBOT LOVES YOU

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

PT6A posted:

It's significantly more difficult than it sounds, too. A good portion of the 3rd- and 4th-year students in my classes can't code anything non-trivial in a non-OO, non-garbage collected language without bitching, moaning and failure, since they're so used to Java. Never mind switching to something significantly more foreign, like a functional language of any type.

Some people's brains just don't work certain ways. My first ever programming language was Haskell, and my first introduction to thinking in 'computer science' terms and reasoning about a problem in a manner that you can break it down into programmatic chunks. 6 years on, I'm still rubbish at it. Problems that I can easily solve in an OO/procedural language are a nightmare for me in Haskell.

Not everyone can be a Charles Atlas programmer that effortlessly (or indeed with effort) grasps every programming paradigm. As long as I don't apply for a job as a quant, I think I can get away with not being able to hack functional programming.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

rt4 posted:

Doing some maintenance on an old app I don't need to touch very often...

php:
<?php

require_once( "../Lib/db/db/db.php" );

?>

As someone who touched php once in the dim and distant past, could you give a more detailed explanation as to why this is bad please? The folder structure doesn't look ideal, or is this to do with symbolic links or something? That's the only stuff I could glean from a quick trawl through the php manual.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
The two features I dislike the most in .NET 3.5 are lambda expressions and the return of the dreaded var. Yes, I know the compiler can work it out. I'm not as smart as the compiler. If I'm looking at your code, there's a good chance there's something wrong with it. Please make my life a bit easier.

At least they gave us automatic properties to make up for it.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
The problem I have with var is that it binds to the strictest return type of a method/constructor, which tends to discourage polymorphism and hence hinder refactoring.

I can appreciate lambda expressions and extension methods speed up the initial developer's output, but it stinks for other people who look at your code.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
It's only an issue when you start writing procedures which accept that implicitly defined variable - many code completion tools and whatnot (I think resharper will, will have to try it tomorrow), will create a method that uses the specific type, rather than something more abstract. If you explicitly declare it as an IEnumerable, it won't.

It's a fairly weak argument, and depends on your coding style/whether you use code completion stuff.

Also, I guess var causes more headaches when it comes to arrays. An array of objects is not the supertype of an array of strings (say), so I think it's best to be explicit when declaring an array.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Ryouga Inverse posted:

Not only is it actually probably that close to done, but the code actually looks like it was written by someone who knew what they were doing.

I'm sure I will find a giant coding horror in here somewhere to whack me upside the head, but so far the only one has been that he didn't know that static classes can have constructors.

Or maybe he realised that static class constructors are the real horror?

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Ryouga Inverse posted:

What's wrong with them? I mean, you can't/shouldn't put any logic in them that depends on the state when they're called, but if all you're doing is making a class with a bunch of constant data in it that can't be constructed through basic initializers, what's wrong with it?

The alternative is having some retarded InitializeConstants() call that has to be done in a bunch of different places.

You can get into headaches if your static constructors reference other static classes with their own static constructors. Also in .NET at least, you have no control over when it executes. And if the constructor throws an exception, it will not and cannot be called again, and then your app domain is a bit hosed.

I'd rather use some form of factory / singleton pattern, and perform the initialisation either when the method is first accessed, or just at the start of the application/main loop/whatever. At least you can re-call your setup code if an exception occurs.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
I'm seriously worried by the number of goons in this thread who cannot spot the fundamental flaws in that Bank Account coding horror.

Bhaal posted:

...If there's a business logic bug in there somewhere, it'll be caught in testing, or customers can simply file a bug report...

This is probably the best troll in the history of man.

Sprawl posted:

Or it could be C# that can sometimes be null or default values.

Directly calling .NET constructors will always return a non-null value. Also, silently logging and proceeding with execution flow on an unexpected null is not necessarily better than just having an exception thrown and letting it percolate up the stack and trapping it further up.

e:I can't type.

Milotic fucked around with this message at 00:33 on Mar 3, 2010

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

nbv4 posted:

code:
$ egrep -R -e recieved . | wc -l
1295

Was that run over directories containing code, or documentation, or input XML files based on an incorrectly spelt schema? (Assuming I'm not barking up the wrong tree, not being a unix guy)

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Seth Turtle posted:

The joke is that 'recieved' (as shown above) is misspelled. The correct spelling is 'received'.

However, according to that egrep there, nbv4 is dealing with a codebase/xml/whatever that has that misspelling in 1295 distinct locations.

EDIT: Misspellings are terrible things. But it's cool to use words like 'klazz' in your code. Don't let anyone tell you otherwise.

No, I got the joke and the meaning of the command (I'm not completely stupid). Just 1295 occurrences of 'recieved' (sic) seems very high for pure code. Hence why asking if there was documentation or xml assets in the folders.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
Bear in mind Middlesex University is ranked 86th in the country for Computer Science, and their sampling in the first paper is decidedly suspect, and at some point involves analysing handwriting because the subjects forgot their nicknames between tests. Also, the authors' tears over Oxbridge are delicious.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Nomnom Cookie posted:

I applied for an internship with a school district, building sites with ASP.NET. I'll probably get it, and if they offer me a job when I graduate my wife wants me to accept. :qq:

Huh? Web development with ASP.NET is fine. There's stuff that could be improved, definitely, and how Microsoft implemented AJAX for ASP.NET can be an abomination unto God sometimes, and the page event life cycle is a bit lovely in places, but really, I've seen worse technologies and frameworks.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
There's been a tendency in my organisation to come up with some real design horrors, where many applications with quite complex behaviour and the need for real time status information have been done as asp.net pages, usually using some Ajax framework rather than WinForms. These are all internal applications. The frustrating thing is that the company just doesn't seem to want to move to flash, silverlight or some other RIA framework. No, we have to have multiple users viewing a page with quite a few nested tables, which refreshes every 5s. And we're making hundreds of calls to SharePoint web services (including security ones, which seem to be the slowest) and AD each time we do this. And we wonder why performance is bad.

Is there some sort of screen history navigation design pattern people use for web pages? Some of our systems chain sub-menu pages, and it's always a complete bitch getting them to return the user to appropriate page in the appropriate state when they click Cancel.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

rt4 posted:

I'm probably going to get poo poo on for asking this, but...
:psyduck:
...under what circumstances would anyone want to restart a server during daily operation?

We have blades at work which restart if a sensor fails - even temporarily. I can see why it makes sense from an ops perspective, but as a developer whose code is running on there, it terrifies the poo poo out of me that it might do it a certain critical juncture.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Shavnir posted:

VBA. VBA is the coding horror.

It's not that bad, and it can actually be a lot more performant than trying to do the same thing through .NET Interop. Hate the player, not the platform. It's the inconsistency in the object models and (for .NET) PIAs that's annoying - did you know that pasting as a picture into PowerPoint 2007 the result from chartObject.Copy() will produce a vastly superior looking result than that from chart.Copy()?

The real coding horror is the deployment mechanism for COM and VSTO solutions. It seems to radically change for every version of Visual Studio and/or .NET runtime. You had your custom Win32 installers, then your custom Win32 installers with .NET lockback registry keys and bundled bootstrappers, then your VSTO installers with custom actions to add every single bloody non-gacd assembly to the CAS, then VSTO installers with custom actions to add everything in the manifest to the inclusion list (unless you want to set-up some sort of trusted certification authority). Arghhh.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
Why are you all being :goonsay: over Haskell anyway? It's Haskell. You do it for a term at uni, scrape a pass in functional programming and drat well make sure you never have to apply for a job where you need to use it again in the real world.

I keep my Haskell programming book on my bookshelf as a stark reminder.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

shrughes posted:

Real programmers [1] use Haskell in the real world. If you thought Haskell was something to discard after one term, well, you're a bad programmer.

[1] People doing interesting things, those who don't like languages because of Stockholm syndrome.

"Real programmers" use what's on the defined strategic technology path for their company.

Also "trap sprung" etc. You chaps are easy pickings.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Ryouga Inverse posted:

I went through the same chain of logic when I was trying to write a game. "How can I make a separate table for each player?"

Luckily I actually asked someone who knew their rear end from a hole in the ground about it.

This is pretty much how Screwturn Wiki works. Each wiki site creates its own set of tables in the database, prepended with the wiki name. Most tables don't have primary keys, including the page version history tables.

I sometimes wonder which is worse - that, default SharePoint wikis or SharePoint wikis extended by KwizCom.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Paul MaudDib posted:

...use of the continue statement...

Unless I'm missing something here, the continue statement isn't a horror in principle. It's a very useful construct.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
We studied Haskell as our first language at uni (it was my first time programming as well). I was so happy when we made the transition to imperative programming.

Seven years on and bits of the bible still give me trouble. I read it on the train every so often.

I'm a software developer for a bank and I'm so happy we don't do functional programming. Wouldn't mind trying aspect-oriented on a proper production app.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

shrughes posted:

I am being serious. Milotic complained about how dumb he is. Which makes him seem stupid. [1] But then he seemed to rub it in by saying he wouldn't mind trying aspect-oriented programming. Which makes it seem like he's really just trolling.

That's how I read it.

[1] Actually, this doesn't make him seem stupid, since people who consider themselves stupid generally aren't that stupid. But then he mentioned aspect-oriented programming.

I'm not a good functional programmer, but I'm a good object oriented programmer. I understand the basics of FP, but the part of the course where we had to write a maze-solving algorithm in it was not my finest hour.

I've worked with aspect oriented programming in the past, but never on a production system. I can see it being useful to solve spaghetti code, or a specific instance where you have a model but the view is composed of several user controls.

Janin posted:

He's implying that Haskell isn't imperative, so yes, he is

Also, some ridiculous percentage (like 75-85%) of OCaml and Haskell programmers work in finance. It's like saying "I'm so glad I'm going to work in the games industry, so I don't have to write in C"

For your first point, I believe this thread has had that discussion in the past. I am sure you can do wonderful things with monads, but Haskell is not a conventional imperative language. Page 325, second edition of "Introduction to FP using Haskell" says:

quote:

In a sense, monadic style enables one to write functional programs that mimic state-based computation,...that mimic imperative programs, those programs constructed in imperative languages such as Pascal and C

For your second point, the vast majority of developers in the finance sector don't do either Haskell or OCaml. That wasn't my point. My point was more like "I work in the games industry, but I'm happy I don't do Silverlight based mobile apps".

Haskell is a niche. An incredibly lucrative niche, but a niche.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Janin posted:

Imperative/declarative is a matter of syntax. Haskell supports both declarative (let-notation) and imperative (do-notation).

I disagree, but I don't want to press this point, since it will ultimately come down to whatever dictionary definition, university text-book you read. I would point out that unfortunately the haskell.org wiki is a bit schizophrenic about whether it is an imperative language is not - saying it is in one article, then not in another.

Janin posted:

Any tutorial/introduction/book about Haskell that doesn't explicitly mention using it as an imperative language (as a replacement for C) is terribly incomplete. For example, I've never even heard of the book you linked as a "bible", and if it was published in 1998(!!) then it's basically worthless for all intents and purposes. I mean, gently caress, that means it was written before Haskell had modules! Throw that poo poo out.

Throw that out? No way man. There was a third edition out, but I was poor at uni so couldn't afford it and the third edition was always checked out of all the libraries.

I would welcome suggestions on alternatives though. I read it from time to time on the train to stretch the mind, but it could be better written.


quote:

If by "finance sector" you mean anyone employed by any financial company, then sure -- most of them are probably using something like COBOL or Java. But if you mean people actually involved in writing finance-related code, almost all of it will be in some sort of functional language. Whether that's ML, OCaml, Matlab, R, Haskell, doesn't really matter.

That's pretty much what I mean. I wouldn't have included Matlab as a 'pure' functional language, but YMMV.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Aleksei Vasiliev posted:

My programming methodology is often programming by permutation. I can code fast as hell sometimes though :buddy:

Doesn't everyone do some programming by permutation when working with poorly designed or 'enterprisey' third party libraries? Stuff like Office OpenXML SDK (or hell most stuff to do with System.XML) springs to mind.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
Look at those C/C++ guys frontin' with their pointers and templates. Time to step to and show them how we do this stuff in the .NET world.

code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FBConsole
{
    public static class CustomExtensions
    {

        public static IEnumerable<TSource> AllOrDefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
        {
            if (source.Count() != 0)
            {
                foreach (var tSourceValue in source)
                {
                    yield return tSourceValue;
                }
            }
            else
            {
                yield return defaultValue;
            }
        }

        public delegate void Func<TSource>(TSource source);

        public static IEnumerable<TSource> ForEach<TSource>(this IEnumerable<TSource> source, Func<TSource> func)
        {
            foreach (var tSourceValue in source)
            {
                func(tSourceValue);
                yield return tSourceValue;
            }
        }

    }

    public class FizzBuzzCharacter
    {
        public string CharacterOrNumber { get; set; }
        public int Order { get; set; }
        public bool DivisibleByThree { get; set; }
        public bool DivisibleByFive { get; set; }
        public bool DivisibleByFifteen { get; set; }
        public bool DivisibleByNada { get; set; }
    }

    static class Program
    {
        static void Main(string[] args)
        {
            List<FizzBuzzCharacter> fbCharacters = new List<FizzBuzzCharacter>();
            //Populate the list.
            fbCharacters.AddRange("fizz".ToCharArray()
                .Select((c, index) => new FizzBuzzCharacter() { 
                    CharacterOrNumber = c.ToString(), 
                    Order = index, 
                    DivisibleByThree = true, 
                    DivisibleByFive = false, 
                    DivisibleByFifteen = true, 
                    DivisibleByNada = false 
                }));
            fbCharacters.AddRange("buzz".ToCharArray()
                .Select((c, index) => new FizzBuzzCharacter() { 
                    CharacterOrNumber = c.ToString(), 
                    Order = index + 4, 
                    DivisibleByThree = false, 
                    DivisibleByFive = true, 
                    DivisibleByFifteen = true, 
                    DivisibleByNada = false 
                }));
            //Don't forget the new line character for matches!
            fbCharacters.AddRange("\n".ToCharArray()
                .Select((c, index) => new FizzBuzzCharacter() { 
                    CharacterOrNumber = c.ToString(), 
                    Order = 9, 
                    DivisibleByThree = true, 
                    DivisibleByFive = true, 
                    DivisibleByFifteen = true, 
                    DivisibleByNada = false 
                }));
            //Select the Fizz Buzz characters which match
            for (int i = 1; i <= 100; i++)
            {
                Type fbType = typeof(FizzBuzzCharacter);
                string methodName = string.Format("DivisibleBy{0}", i % 15 == 0 ? "Fifteen" : i % 5 == 0 ? "Five" : i % 3 == 0 ? "Three" : "Nada");
                var defaultFbc = new FizzBuzzCharacter() { CharacterOrNumber = i.ToString() + "\n" };

                var results = fbCharacters
                    .Where(fbc => (bool)fbType.InvokeMember(methodName, System.Reflection.BindingFlags.GetProperty, null, fbc, null))
                    .OrderBy(fbc => fbc.Order)
                    .AllOrDefaultIfEmpty(defaultFbc)
                    .ForEach(fbc => Console.Write(fbc.CharacterOrNumber));
                int x = results.Count(); //Force evaluation

            }
        }
    }

}

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
Thank you for all the kind words. I found it surprisingly fun. There's a couple of problems with that solution, one of which being it is far too quick - you don't really get the excitement of waiting for the solution. We could throw in Thread.Sleeps, but that's far too predictable. We want people on the edge of their seats.

So I present: GeneticFizzBuzz, with a mutation chance of around 1 in 1 million.

code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeneticFizzBuzzConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;
            var idealFizzBuzz = FizzBuzzSelector.BreedTheBuggersUntilOneFits();
            DateTime endTime = DateTime.Now;
            foreach (KeyValuePair<int, string> kvp in idealFizzBuzz.Map)
            {
                Console.WriteLine(string.Format("{0} : {1}", kvp.Key, kvp.Value));
            }
        }
    }

    public class FizzBuzzSelector
    {
        public static FizzBuzzCandidateSolution BreedTheBuggersUntilOneFits()
        {
            //Mitochondrial Eve
            var eve = new FizzBuzzCandidateSolution();
            for (int i = 1; i <= 100; i++) { eve.Map.Add(i, "Fizz"); }
            //Piltdown Buzz
            var piltdown = new FizzBuzzCandidateSolution();
            for (int i = 1; i <= 100; i++) { piltdown.Map.Add(i, "Buzz"); }

            var population = new List<FizzBuzzCandidateSolution>();
            population.Add(eve);
            population.Add(piltdown);
            double generations = 0;
            int bestMatch = 0;
            while (!population.Any(p => p.Suitability() == 100))
            {
                //Select the top two from the population
                var topFittest = population.OrderByDescending(p => p.Suitability()).Take(2);
                var newMother = topFittest.ElementAt(0);
                var newFather = topFittest.ElementAt(1);
                var baby = FizzBuzzBreeder.Mate(newMother, newFather);
                population = new List<FizzBuzzCandidateSolution>();
                population.Add(newMother); population.Add(newFather); population.Add(baby);
                generations++;
                int candidateBestMatch = Math.Max(
                    Math.Max(newMother.Suitability(), newFather.Suitability())
                    , baby.Suitability());
                if (candidateBestMatch > bestMatch)
                {
                    bestMatch = candidateBestMatch;
                    Console.WriteLine(string.Format("New best Match at {0} generations: {1}", generations, bestMatch));
                }
            }
            return population.First(p => p.Suitability() == 100);
        }
    }

    public class FizzBuzzCandidateSolution
    {
        public FizzBuzzCandidateSolution()
        {
            Map = new Dictionary<int, string>();
        }

        public Dictionary<int, string> Map { get; set; }

        private int? _Score = null;


        //Assume we only call this once and the Map never changes contents
        public int Suitability()
        {
            if (_Score == null)
            {
                _Score = 0;
                foreach (KeyValuePair<int, string> kvp in Map)
                {
                    if (Suitable(kvp.Key, kvp.Value)) { _Score++; }
                }
            }
            return _Score.Value;
        }

        public static bool Suitable(int i, string value)
        {
            if (i % 15 == 0 && value.Equals("FizzBuzz")) { return true; }
            else if ((i % 15 != 0) && (i % 5 == 0) && value.Equals("Buzz")) { return true; }
            else if ((i % 15 != 0) && (i % 3 == 0) && value.Equals("Fizz")) { return true; }
            else if ((i % 5 != 0) && (i % 3 != 0) && value.Equals(i.ToString())) { return true; }
            return false;
        }
    }


    public class FizzBuzzBreeder
    {
        private static Random Chance = new Random();
        private static Random PerformMutationChance = new Random();

        public static FizzBuzzCandidateSolution Mate(FizzBuzzCandidateSolution mother, FizzBuzzCandidateSolution father)
        {
            var child = new FizzBuzzCandidateSolution();
            foreach (var key in mother.Map.Keys)
            {
                var childValue = MateValue(key, mother.Map[key], father.Map[key]);
                child.Map.Add(key, childValue);
            }

            return child;
        }

        private static string MateValue(int key, string motherValue, string fatherValue)
        {
            //Can we just use the mother or father?
            if (FizzBuzzCandidateSolution.Suitable(key, motherValue))
            {
                return motherValue;
            }
            if (FizzBuzzCandidateSolution.Suitable(key, fatherValue))
            {
                return fatherValue;
            }
           

            //Should we use the mutation?
            int performMutation = PerformMutationChance.Next(1000000);
            if (performMutation == 0)
            {
                //Not suitable, let's randomly mutate.
                int mutationChance = Chance.Next(4);
                //Work out what the mutation would be:
                string mutation;
                switch (mutationChance)
                {
                    case 0: mutation = key.ToString(); break;
                    case 1: mutation = "Fizz"; break;
                    case 2: mutation = "Buzz"; break;
                    case 3: mutation = "FizzBuzz"; break;
                    default: mutation = "IMPOSSIBLE"; break;
                }

                return mutation;
            }
            else if (performMutation % 2 == 0)
            {
                return motherValue;
            }
            else
            {
                return fatherValue;
            }
        }
    }
}

It took me about 26 minutes 47 seconds to compute the results on my PC and required 25880962 generations. But next time it could be as much as an hour, as little as 1 second.

Here's how it progressed



(Why yes, I am on holiday)

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Ithaqua posted:

You are a god of overcomplication. I'm stunned.

[edit] Although, I noticed you're not really taking advantage of the paralell task library on this one. I took the liberty of altering your code thusly:

code:
        public static FizzBuzzCandidateSolution Mate(FizzBuzzCandidateSolution mother, FizzBuzzCandidateSolution father)
        {
            var child = new FizzBuzzCandidateSolution();
            
            Parallel.ForEach(mother.Map.Keys, key =>
                                                  {
                                                      lock(child.Map)
                                                      {
                                                          child.Map.Add(key, MateValue(key, mother.Map[key], father.Map[key]));   
                                                      }
                                                  });

            return child;
        }
It seems to be working, although I'm not 100% sure it'll return the correct answer, since Dictionary isn't thread-safe as far as I know. It's certainly keeping my 8 CPU cores occupied

Ah yeah, that's nice. Now it's web-scale. As for being a god of overcomplication, it comes naturally. Up until Friday I was tech lead for the SharePoint platform in my country's central bank. So Enterprise, SharePoint AND Government. I have jury rigged far more hideously complex things than that in my time. Most of my maintenance guides start off apologising for the system.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

pseudorandom name posted:

I don't see what's so bad about marking up data so that search engines can identify, extract and index it.

It's not just search engines. Enterprise / public sector is also interested in this stuff. You can glean, or attempt to glean a lot of useful information about inflation and prices by screen-scraping information off Tesco.com and the like. And then they change their layout, or add multiples/weights, or add offers, and it turns into a bit of an arms race until you finally say "gently caress it". schema.org and whatnot would be a godsend.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
I was going to do a FizzBuzz using Rx, but Rx is a little funky. So I thought I'd see how much I could abuse the language instead. The below code works. You wouldn't expect it to, but the first call to GetAction is with a value of 1, and not 0 as you would initially intuit.

code:
   class FizzBuzzThatWorksButIAmBuggeredIfIKnowWhy
    {

        public void Execute()
        {
            var allActions = BuildAction(() => { }, 0);
            allActions();
        }

        public Action BuildAction(Action action, int i)
        {
            if (i == 100) { return action; }
            Action wrapperAction = () => { action(); GetAction(i)(); };
            return BuildAction(wrapperAction, ++i);
        }

        public Action GetAction(int i)
        {
            switch (i % 15)
            {
                case 0:
                    return () => Console.WriteLine(i + ": FizzBuzz");
                default:
                    {
                        switch (i % 5)
                        {
                            case 0:
                                return () => Console.WriteLine(i + ": Buzz");
                            default:
                                {
                                    switch (i % 3)
                                    {
                                        case 0:
                                            return () => Console.WriteLine(i + ": Fizz");
                                        default:
                                            return () => Console.WriteLine(i);
                                    }
                                };
                                break;
                        }
                    };
                    break;
            }
        }

        static void Main(string[] args)
        {
            var p = new FizzBuzzThatWorksButIAmBuggeredIfIKnowWhy();
            p.Execute();
        }
    }

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
Arguing about coding style is for petty people. More cultured, intelligent people argue about the singleton pattern.

(I have had an almost blazing row about this in the past)

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
It's not really that much of a horror. Needs a comment describing what it does / the expected format of the Word document, and probably some better error handling / checking for nulls, but that looks like fairly standard Linq to XML.

The Open XML SDK was always a bit horrible. It's enough to make you miss PIAs sometimes.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

BonzoESC posted:

Couldn't you use an xpath?
code:
textValue = row.down('descendant-or-self::tablecell/descendant::paragraph/descendant::run/descendant::text').first.text

In my opinion, XPath/pre-Linq-to-Xml processing isn't great in .NET. It's painful having to mess around with Xml namespaces and the libraries and concepts aren't very intuitive. Additionally, the Office Open XML format is quite verbose and complex and does some surprising things that can make XPath a bad choice. The documents are composed of several zipped folders, Xml files and binary resources.

Case in point, Excel supports drag-and-filling of a formula into adjacent cells, with relative cells changing as the columns and rows change. However in the Xml, the adjacent cells are stored with a reference the formula in the master cell, with interpolation of the actual formula being done at runtime. I had to parse the bloody things once, that sure was fun!

So yeah, Linq to Xml coupled with the OpenXML SDK is actually the sanest solution here, apart from possibly using the PIAs if performance isn't a problem and you don't mind all the 'joys' that come from running Word in headless mode.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

aleph1 posted:

And what do you think happens with:

code:
try {
  foo();
  return 0;
} catch (Exception e) {
} finally {
  System.err.println("bar");
}
(finally always runs unless you manage to crash the JVM or call exit() somewhere)

Cross-thread Thread.Abort() will do the trick as well in .NET 1.0 and 1.1. It's been fixed since .NET 2.0, but TerminateThread can still abort in the middle of a finally block.

e: There's a couple of .NET library calls which can call Thread.Abort if you try to access COM objects in a funny way, which is a bit of a coding horror / annoying as hell.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
I haven't done one of these in a while: multi-threaded FizzBuzz.

code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace MultiThreadedFizzBuzz
{
    class MultiThreads
    {
        public void StartAll()
        {
            Thread numThread = new Thread(RunInts);
            Thread fizzThread = new Thread(RunFizz);
            Thread buzzThread = new Thread(RunBuzz);
            Thread fizzBuzzThread = new Thread(RunFizzBuzz);
            numThread.Start();
            Thread.Sleep(200);  //Dark magic.
            fizzThread.Start();
            buzzThread.Start();
            fizzBuzzThread.Start();
        }

        private volatile int i = 1;

        private object LockObject = new object();

        private object FizzObject = new object();

        private object BuzzObject = new object();

        private object FizzBuzzObject = new object();

        public void RunInts()
        {
            lock (FizzObject)
            {
                lock (BuzzObject)
                {
                    lock (FizzBuzzObject)
                    {
                        while (i <= 100)
                        {
                            if (i % 15 == 0)
                            {
                                Monitor.PulseAll(FizzBuzzObject);
                                Monitor.Wait(FizzBuzzObject);
                            }
                            else if (i % 3 == 0)
                            {
                                Monitor.PulseAll(FizzObject);
                                Monitor.Wait(FizzObject);
                            }
                            else if (i % 5 == 0)
                            {
                                Monitor.PulseAll(BuzzObject);
                                Monitor.Wait(BuzzObject);
                            }
                            else
                            {
                                Console.WriteLine(i);
                            }
                            i++;
                        }
                    }
                }
            }
        }

        public void RunFizz()
        {
            lock (FizzObject)
            {
                while (i <= 100)
                {
                    Console.WriteLine("Fizz");
                    Monitor.PulseAll(FizzObject);
                    Monitor.Wait(FizzObject);
                }
            }
        }

        public void RunBuzz()
        {
            lock (BuzzObject)
            {
                while (i <= 100)
                {
                    Console.WriteLine("Buzz");
                    Monitor.PulseAll(BuzzObject);
                    Monitor.Wait(BuzzObject);
                }
            }
        }

        public void RunFizzBuzz()
        {
            lock (FizzBuzzObject)
            {
                while (i <= 100)
                {
                    Console.WriteLine("FizzBuzz");
                    Monitor.PulseAll(FizzBuzzObject);
                    Monitor.Wait(FizzBuzzObject);
                }
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var m = new MultiThreads();
            m.StartAll();
            Console.ReadLine();
        }
    }

}

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Mogomra posted:

I'm actually really interested to hear what the issues with Node.js are. I keep hearing people say that it's the next PHP, but I don't hear any clear cut reasons why. Is it just that there's really no one way to skin a cat in javascript? Or is there even more craziness that I don't know about?

e: Also null and undefined? Really? The more I think about it the more I think I'm answering my own question. I'd still like to hear everyone's input.

I am not a node.js guru, but two core things are 1) callbacks and 2) event loops. The first tends to result in your code being "inside out" when chaining callbacks. The second has its place, but when abused results in some fiendishly difficult to debug systems. Also, as good as V8 is, it can only optimise so much given that it has to deal with a dynamic, weakly typed language. I'd also make the probably controversial statement that weakly typed languages aren't as amenable to the types of refactoring that happens on medium to larger scale projects. It's nice being able to make a change and know the compiler will scream at you to tidy up in all the places you'd completely forgotten about.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
That doesn't sound like such a horror. Refactors / rewrites don't deliver value in themselves. And if it's an enterprise customer, they'll have their own QA processes where you can continue to work on v1.1 whilst they review v1.0.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

tef posted:

If we're honest, it's more like:

Writes Sql Query, Watches it turn into series of streams, cached operations etc,

Rewrites Sql Query after inspecting the query plan, tries again.

Laughs at nosql people writing what they want directly rather than second guessing a non deterministic query planner.

You missed off:

Update statistics
Wait
Pray
Re-run
Swear
Add missing index that the query plan is complaining about, even though you know it won't use it
Re-run
Moan softly as it still does a full table scan

I like working with traditional RDBMS, but let's be honest, it's more a craft than a science.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Zombywuf posted:

Well, if you will trust the magic index hinter (hint: don't).

I don't. That said, it has helped when someone creates a table with a foreign key and forgets to create an index on the foreign key. The % of batch information in the query plan is also utterly misleading. No Gods, no masters, only SET STATISTICS TIME ON.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
Well Java has one over C# in that enums can have properties, methods and constructors, which can be handy sometimes.

Re: C#, the 1.0/2.0 APIs feel a bit janky or inconsistent in parts. Some methods return strings, some methods return DirectoryInfo/FileInfos, it's not obvious from the name if something will return a trailing slash or what, the full Win32 api for process manipulation isn't exposed in the Process class, so if you need some specific functionality, holy balls you end up writing a lot of extern stuff and re-implementing the Process class (which is not easy). There's no nice way of taking the redirected Console.Out and Console.Error (which aren't actually STDOUT/STDERR annoyingly) and merging them so the output is definitely in the order they were written to.

More recently, I think the async/await and TPL is a bit leaky in terms of abstraction - there's lots of subtleties going on under the hood that you need to understand and you can easily end up screwing yourself over unintentionally (think of ConfigureAwait synchronization deadlocks when you use TPL code in a GUI.)

Lack of customisation around the JIT or the GC. The relatively massive penalties incurred in short lived .NET apps if you try to access the ConfigurationManager.AppSettings. Not being able to change the default app domain's DLL search path. Interactions between app domains being fairly messy and an absolutely stellar way to gently caress yourself over with type serialization issues if you don't know what you're doing. Custom exceptions (so deriving from Exception) not being Serializable by default, leading to misleading exceptions if an exception crosses an app domain boundary (for the love of god, never write custom exceptions).

Libraries and their handling of Xml namespaces, including the default one. The 1.0 library is bad, but the XDocument / XPath stuff isn't much better. NamespaceTableManager and all that bollocks. 99% of the time, we don't care.

WPF needs streamlining and bugs being fixed in controls (Accordion control in designer mode has been broken for years now, throws NREs). Language features / extensions to make multi-field validation, or edit/revert/mark as unsaved not a complete PITA full of boilerplate to do.

I very much enjoy working with C#, but I do sometimes wish they could throw out a lot of the window and start again.

Adbot
ADBOT LOVES YOU

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde

Monkeyseesaw posted:

The whole W*F generation of frameworks all seem to suffer from severe architecture astronautics, now that I think about it. WCF, WPF, etc. are (or were) all very difficult to use out of the box for anything useful and are generally unhelpful when things go sideways.

Windows Workflow Foundation was the flakiest piece of crap ever and was even flakier when added to SharePoint (which also suffers from architecture astronautics and being firmly in the ASP.NET WebForms camp rather than the MVC camp). WPF always suffered from issues whereby something that you think would be easy or even built into a default control, turned out to be super-hard. And the whole DependencyObject/DependencyProperty malarkey was a bad abstraction. I get that they allegedly did it for performance, but WPF perf is kinda bad anyway, but you end up having to do lots of boilerplate around DO/DPs which wasn't always easy to remember. Biggest issue with WPF is that drag/drop and similar user interactions don't behave exactly the same as Windows Explorer - you had to write custom code to approximate it.

I think Microsoft have gotten a lot better at this stuff recently. Doing out of band releases means things can be polished and don't hold up VS releases and vice versa. (Also there is a bigger expectation that libraries can change fairly dramatically until the first proper RC)

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