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
Pixelboy
Sep 13, 2005

Now, I know what you're thinking...

Ithaqua posted:

TFS really is a wonderful product for those of us who are Microsoft-centric. I want to learn git better, but all of the commands are scary and obtuse. :(

religion aside, Mercurial is probably what you want in this case.

Adbot
ADBOT LOVES YOU

Sang-
Nov 2, 2007

qntm posted:

It's true, comprehending code does become rather difficult when you start ignoring random characters.

in languages where variables are $var_name, it can be quite easy to miss (!$, especially when you're tired. (in perl I tend to use (not $var) or unless

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Otto Skorzeny posted:

Perhaps, if there were some way to put associated Names in their own Space, we wouldn't have to prefix them ourselves to prevent Collisions. But alack!, such a technology is beyond our grasp, despite our most earnest Declarations.

PHP only got namespaces relatively recently, and a code obfuscation tool that doesn't work on terrible shared hosts running ancient versions of PHP is extra pointless.

dexter
Jun 24, 2003

Ithaqua posted:

TFS really is a wonderful product for those of us who are Microsoft-centric. I want to learn git better, but all of the commands are scary and obtuse. :(

The commands are really easy if you have half a clue and just some basic SVN experience. Ignore the stuff about how it's a directed acyclic graph and all that; it's helpful when understanding rebasing and how branches/tags actually work but you really don't need it just to escape lovely VCSs.

Zorro KingOfEngland
May 7, 2008

Found this while I was refactoring some of our code. This stuff has been in production for 4 years.

Java code:
subStatus.setStatus(xmlHelper.getMessage(submitResponse)[0]); 	// TODO:
																	// See
																	// if
																	// the
																	// [0]
																	// actually
																	// worked

how!!
Nov 19, 2011

by angerbot
If the horror fits on on eline, its not an horror.

Python code:
    def create_recurring_jobs(self, test_availability=False):
        data = {
                "recurring":True,
                "recurring_job_key": maindb.Key(encoded = self.data["key"]), 
                "customer_key": self.data["customer_key"],
                "gc_key": self.data["gc_key"],
                "extras": self.data["extras"],
                "customer_name": self.data["customer_name"],
                "customer_phone": self.data["customer_phone"],
                "customer_email": self.data["customer_email"],
                "bedrooms": self.data["bedrooms"],
                "bathrooms": self.data["bathrooms"],
                "sqft": self.data["sqft"],
                "num_hours":self.data["num_hours"],
                "address_street1": self.data["address_street1"],
                "address_street2": self.data["address_street2"],
                "address_city": self.data["address_city"],
                "address_state": self.data["address_state"],
                "address_postal_code":self.data["address_postal_code"],
                "address_lat": self.data["address_lat"],
                "address_long": self.data["address_lng"],
                "description": self.data["description"],
                "timezone": self.data["timezone"],
                "customer_discounts": self.data["customer_discounts"],
                "discounts": self.data["discounts"],
                "customer_price": self.data["customer_price"],
                "customer_totalprice": self.data["customer_totalprice"],
                "sbusinesskeys": self.data["sbusinesskeys"],
                "team_size": self.data["team_size"],
                "status":"submitted",
                "timezone":self.data["recurring_timezone"],
                "cckey": self.data["cckey"]}
    
        if "cleaning supplies" in self.data["fees"]:
            data.update({"customer_price": data["num_hours"]*config.SETTINGS["hourlyrate"]*data["team_size"]})
            if data["customer_price"]>80:
                supplies_fee = config.SETTINGS['supplies_fee']
            else:
                supplies_fee = config.SETTINGS['supplies_fee']/2
            data.update({"fees":["cleaning supplies"],"customer_fees":float(supplies_fee),"customer_discounts":0.0})
            data.update({"customer_totalprice": data["customer_price"]-data["customer_discounts"]+data["customer_fees"]})
        else:
            data.update({"customer_price": data["num_hours"]*config.SETTINGS["hourlyrate"]*data["team_size"]})
            data.update({"fees":[],"customer_fees":0.0,"customer_discounts":0.0})
            data.update({"customer_totalprice": data["customer_price"]-data["customer_discounts"]+data["customer_fees"]})
    
    
        contractlength = 4#months
    
        #if testing availability, need to retrieve mastercalendar for address/num_hours/team_size/city, and if sbusinesskey exists, need to retrieve calendar for specific cleaner
        if test_availability:
            gen_hits,gen_misses,specific_hits,specific_misses = [0,0,0,0]
            if not self.gen_avails:
                self.gen_avails = get_available_dates(data["address_postal_code"],data["address_city"],data["num_hours"],data["team_size"])
            if not self.specific_avails:
                if len(data["sbusinesskeys"])>0:
                    tmp_avails = []
                    for sbusinesskey in data["sbusinesskeys"]:
                        tmp_avails += [get_available_dates(data["address_postal_code"],data["address_city"],data["num_hours"],data["team_size"],businesskey=sbusinesskey)] 
                    if len(tmp_avails)>0:
                        specific_avails=tmp_avails[0]
                        final_specific_avails = tmp_avails[0]
                        for i in range(1,len(tmp_avails)):
                            compare_avails = tmp_avails[i]
                            for start_date in specific_avails.keys():
                                for start_time in specific_avails[start_date]:
                                    if start_date not in compare_avails.keys() or start_time not in compare_avails[start_date]:
                                        final_specific_avails[start_date] = [ele for ele in final_specific_avails[start_date] if ele != start_time]
                        specific_avails = final_specific_avails
                    else:
                        specific_avails = tmp_avails[0]
                else:
                    specific_avails = gen_avails
                self.specific_avails = specific_avails
    
    
        # check if there exists a customer who has this email.  if not, create one. then, update job with customer_key
        if not test_availability:
            if self.data.has_key("customer_key") and self.data["customer_key"]:
                customer = [db.CUSTOMER.get(self.data["customer_key"])]
            else:
                customer = db.CUSTOMER.get_entities({"email":self.data["customer_email"]})
            if len(customer)==0:
                customer_data = {
                        "email":self.data["customer_email"],
                        "name":self.data["customer_name"],
                        "phone": self.data["customer_phone"],
                }
                if self.data["address_street1"]:
                    customer_data.update({
                        "address_street1_list":[self.data["address_street1"]],
                        "address_street2_list":[self.data["address_street2"]],
                        "address_city_list":[self.data["address_city"]],
                        "address_state_list":[self.data["address_state"]],
                        "address_postal_code_list":[self.data["address_postal_code"]],
                        "address_country_list":["US"],
                        "sqft": int(self.data["sqft"]),
                        "bedrooms": float(self.data["bedrooms"]),
                        "bathrooms": float(self.data["bathrooms"]),
                        "num_hours": float(self.data["num_hours"]),
                        })
                customerkey = current_customer.create_account(customer_data)
            else:
                customer = customer[0]
                customer_data = {"name":self.data["customer_name"],
                        "email":self.data["customer_email"],
                        "sqft": int(self.data["sqft"]),
                        "bedrooms": float(self.data["bedrooms"]),
                        "bathrooms": float(self.data["bathrooms"]),
                        "num_hours": float(self.data["num_hours"]),
                        "phone":self.data["customer_phone"]}
                if (self.data["address_street1"] and self.data["address_street1"] not in customer["address_street1_list"]) or (self.data["address_street2"] and self.data["address_street2"] not in customer["address_street2_list"]) or (self.data["address_city"] and self.data["address_city"] not in customer["address_city_list"]) or (self.data["address_state"] and self.data["address_state"] not in customer["address_state_list"]) or (self.data["address_postal_code"] and self.data["address_postal_code"] not in customer["address_postal_code_list"]):
                    customer_data.update({
                        "address_street1_list":customer["address_street1_list"]+[self.data["address_street1"]],
                        "address_street2_list":customer["address_street2_list"]+[self.data["address_street2"]],
                        "address_city_list":customer["address_city_list"]+[self.data["address_city"]],
                        "address_state_list":customer["address_state_list"]+[self.data["address_state"]],
                        "address_postal_code_list":customer["address_postal_code_list"]+[self.data["address_postal_code"]],
                        "address_country_list":customer["address_country_list"]+["US"],
                        })
                db.CUSTOMER.update_entity(customer["key"],customer_data)
                customerkey = customer["key"]
            data.update({"customer_key":customerkey})
    
    
        if self.data["recurring_frequency"] == "onetime":
            start = datetime.datetime.strptime("%s %s" % (self.data["recurring_start_date"], self.data["recurring_start_time"].upper()), '%m/%d/%Y %I:%M %p')
            start = pytz.timezone(self.data["timezone"]).localize(start)
            data.update({"start":start})
            if not test_availability:
                job = db.JOB.add_entity(data)
                job_obj = get(job)
                if len(data["sbusinesskeys"])>0:
                    for businesskey in data["sbusinesskeys"]:
                        job_obj.send_claim_code(businesskey,skip_activity=True)
                job_obj.apply_credits()
                job_obj.apply_gift_credits()
            else:
                if self.data["recurring_start_date"] in self.gen_avails.keys() and self.data["recurring_start_time"].upper() in self.gen_avails[self.data["recurring_start_date"]]:
                    gen_hits += 1
                else:
                    gen_misses += 1
                if self.data["recurring_start_date"] in self.specific_avails.keys() and self.data["recurring_start_time"].upper() in self.specific_avails[self.data["recurring_start_date"]]:
                    specific_hits += 1
                else:
                    specific_misses += 1
    
    
            recurring_expiration = start
        elif self.data["recurring_frequency"] == "list":
            starts = []
            for i in range(0,len(self.data["recurring_start_dates"])):
                start_date = self.data["recurring_start_dates"][i]
                start_time = self.data["recurring_start_times"][i]
                start = datetime.datetime.strptime("%s %s" % (start_date, start_time.upper()), '%m/%d/%Y %I:%M %p')
                start = pytz.timezone(self.data["timezone"]).localize(start)
                starts += [start]
                data.update({"start":start})
                if not test_availability:
                    job = db.JOB.add_entity(data)
                    job_obj = get(job)
                    if len(data["sbusinesskeys"])>0:
                        for businesskey in data["sbusinesskeys"]:
                            job_obj.send_claim_code(businesskey,skip_activity=True)
                    job_obj.apply_credits()
                    job_obj.apply_gift_credits()
                else:
                    if start_date in self.gen_avails.keys() and start_time.upper() in self.gen_avails[start_date]:
                        gen_hits += 1
                    else:
                        gen_misses += 1
                    if start_date in self.specific_avails.keys() and start_time.upper() in self.specific_avails[start_date]:
                        specific_hits += 1
                    else:
                        specific_misses += 1
    
            min_start = starts[0]
            max_start = starts[0]
            for start in starts:
                if start<min_start:
                    min_start = start
                if start > max_start:
                    max_start = start
            recurring_expiration = max_start
    
        elif self.data["recurring_frequency"] == "weekly":
            start = datetime.datetime.strptime("%s %s" % (self.data["recurring_start_date"], self.data["recurring_start_time"].upper()), '%m/%d/%Y %I:%M %p')
            start = pytz.timezone(self.data["timezone"]).localize(start)
    
            for i in range(0,contractlength*5):
                new_start = start+datetime.timedelta(days=7*i)
                #manually setting hour due to daylight savings time possible bug
                data.update({"start":pytz.timezone(self.data["timezone"]).localize(datetime.datetime.strptime("%s/%s/%s %s" % (new_start.month,new_start.day,new_start.year, self.data["recurring_start_time"].upper()), '%m/%d/%Y %I:%M %p'))})
                if not test_availability:
                    job = db.JOB.add_entity(data)
                    job_obj = get(job)
                    if len(data["sbusinesskeys"])>0:
                        for businesskey in data["sbusinesskeys"]:
                            job_obj.send_claim_code(businesskey,skip_activity=True)
                    job_obj.apply_credits()
                    job_obj.apply_gift_credits()
                else:
                    new_start_date = "%s/%s/%s" % (new_start.month,new_start.day,new_start.year)
                    new_start_time = self.data["recurring_start_time"]
                    if new_start_date in self.gen_avails.keys() and new_start_time.upper() in self.gen_avails[new_start_date]:
                        gen_hits += 1
                    else:
                        gen_misses += 1
                    if new_start_date in self.specific_avails.keys() and new_start_time.upper() in self.specific_avails[new_start_date]:
                        specific_hits += 1
                    else:
                        specific_misses += 1
                recurring_expiration = new_start
        elif self.data["recurring_frequency"] == "biweekly":
            start = datetime.datetime.strptime("%s %s" % (self.data["recurring_start_date"], self.data["recurring_start_time"].upper()), '%m/%d/%Y %I:%M %p')
            start = pytz.timezone(self.data["timezone"]).localize(start)
            for i in range(0,contractlength*30):
                new_start = start+datetime.timedelta(days=1*i)
                weekday = util.get_weekday(new_start)
                nth_weekday = util.get_nthdayofweek(new_start)
    
                logging.info(str(self.data))
                passed = False
                if self.data["recurring_biweekly_weeks"] == "1and3" and weekday == self.data["recurring_weekday"] and (nth_weekday ==1 or nth_weekday==3):
                    passed = True
                if self.data["recurring_biweekly_weeks"] == "2and4" and weekday == self.data["recurring_weekday"] and (nth_weekday ==2 or nth_weekday==4):
                    passed = True
                if not passed:
                    continue
                data.update({"start":pytz.timezone(self.data["timezone"]).localize(datetime.datetime.strptime("%s/%s/%s %s" % (new_start.month,new_start.day,new_start.year, self.data["recurring_start_time"].upper()), '%m/%d/%Y %I:%M %p'))})
                if not test_availability:
                    job = db.JOB.add_entity(data)
                    job_obj = get(job)
                    if len(data["sbusinesskeys"])>0:
                        for businesskey in data["sbusinesskeys"]:
                            job_obj.send_claim_code(businesskey,skip_activity=True)
                    job_obj.apply_credits()
                    job_obj.apply_gift_credits()
    
                else:
                    new_start_date = "%s/%s/%s" % (new_start.month,new_start.day,new_start.year)
                    new_start_time = self.data["recurring_start_time"]
                    if new_start_date in self.gen_avails.keys() and new_start_time.upper() in self.gen_avails[new_start_date]:
                        gen_hits += 1
                    else:
                        gen_misses += 1
                    if new_start_date in self.specific_avails.keys() and new_start_time.upper() in self.specific_avails[new_start_date]:
                        specific_hits += 1
                    else:
                        specific_misses += 1
                recurring_expiration = new_start
    
        elif self.data["recurring_frequency"] == "monthly":
            start = datetime.datetime.strptime("%s %s" % (self.data["recurring_start_date"], self.data["recurring_start_time"].upper()), '%m/%d/%Y %I:%M %p')
            start = pytz.timezone(self.data["timezone"]).localize(start)
    
            for i in range(0,contractlength*30):
                new_start = start+datetime.timedelta(days=1*i)
                weekday = util.get_weekday(new_start)
                nth_weekday = util.get_nthdayofweek(new_start)
    
                passed = False
                if self.data["recurring_monthly_nth_weekday"] == str(nth_weekday) and weekday == self.data["recurring_weekday"]:
                    passed = True
                if not passed:
                    continue
                data.update({"start":pytz.timezone(self.data["timezone"]).localize(datetime.datetime.strptime("%s/%s/%s %s" % (new_start.month,new_start.day,new_start.year, self.data["recurring_start_time"].upper()), '%m/%d/%Y %I:%M %p'))})
                if not test_availability:
                    job = db.JOB.add_entity(data)
                    job_obj = get(job)
                    if len(data["sbusinesskeys"])>0:
                        for businesskey in data["sbusinesskeys"]:
                            job_obj.send_claim_code(businesskey,skip_activity=True)
                    job_obj.apply_credits()
                    job_obj.apply_gift_credits()
                else:
                    new_start_date = "%s/%s/%s" % (new_start.month,new_start.day,new_start.year)
                    new_start_time = self.data["recurring_start_time"]
                    if new_start_date in self.gen_avails.keys() and new_start_time.upper() in self.gen_avails[new_start_date]:
                        gen_hits += 1
                    else:
                        gen_misses += 1
                    if new_start_date in self.specific_avails.keys() and new_start_time.upper() in self.specific_avails[new_start_date]:
                        specific_hits += 1
                    else:
                        specific_misses += 1
                recurring_expiration = new_start
        if not test_availability:
            if self.data["recurring_frequency"] == "list":
                db.RECURRINGJOB.update_entity(self.data["key"],{"recurring_expiration":recurring_expiration,"start":min_start})
            else:
                db.RECURRINGJOB.update_entity(self.data["key"],{"recurring_expiration":recurring_expiration})
    
            #create recurring job claim code for each business
            for businesskey in self.data["sbusinesskeys"]:
                code = util.nicepass(3,3)
                while db.CLAIMCODE.get_entity({"code":code}, keys_only=True):
                    logger.output("REPEAT CLAIM CODE")
                    code = util.nicepass(4,3)
                
                data = {
                    "businesskey": businesskey,
                    "jobkey": self.data["key"],
                    "code": code,
                    "recurring": True,
                }        
            
                recurringclaimcodekey = db.CLAIMCODE.add_entity(data)
                logging.info("Created recurring job claim code")
    
            activity.log("recurring-job-confirmed-customer", {"job":self})
        if test_availability:
            general_availability = float(gen_hits)/(gen_hits+gen_misses)
            specific_availability = float(specific_hits)/(specific_hits+specific_misses)
            return [general_availability,specific_availability]
The current project I'm working on is entirely written like this. (50,000+ lines). The sad part i that the entire project could be re-written using django and could be a fraction of the size, but "that would take forever". So instead I spend hours pouring over this poo poo which takes forever anyways.

how!! fucked around with this message at 17:27 on Jan 16, 2013

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde
Problem: A procedure is too long.
Solution: Django! :confused:

There are options somewhere in between.

Gazpacho fucked around with this message at 20:31 on Jan 16, 2013

Sedro
Dec 31, 2008
Solution:

how!! posted:

the entire project could be re-written

shrughes
Oct 11, 2008

(call/cc call/cc)

how!! posted:

The sad part i that the entire project could be re-written using django and could be a fraction of the size

So why are you pasting the code that wouldn't be made any smaller?

Zamujasa
Oct 27, 2010



Bread Liar

how!! posted:

If the horror fits on on eline, its not an horror.
My boss begs to differ:
php:
<?
/* https://oursite.com/s3cr37s7uff/do_cmd.php : 17 */

$output = shell_exec("php /var/important.php ". mysql_real_escape_string($_GET['myvar']));

?>
:smugbert:

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker

Zamujasa posted:

My boss begs to differ:
php:
<?
/* [url]https://oursite.com/s3cr37s7uff/do_cmd.php[/url] : 17 */

$output = shell_exec("php /var/important.php ". mysql_real_escape_string($_GET['myvar']));

?>
:smugbert:

Ok, that one's funny.

JawnV6
Jul 4, 2004

So hot ...

Gazpacho posted:

Problem: A procedure is too long.
Solution: Django! :confused:

There are options somewhere in between.

Naw I'm totally sure he'll remember the supply fee discount on small orders in the re-write since's it is adequately documented outside of the code.

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

how!! posted:

The sad part i that the entire project could be re-written using django and could be a fraction of the size, but "that would take forever".

Oh, it's you again. Does Django 1.4 do your read your order processing manual for you now? I haven't used the newer versions, but that feature would certainly help with this very specific procedure.

JawnV6 posted:

Naw I'm totally sure he'll remember the supply fee discount on small orders in the re-write since's it is adequately documented outside of the code.

Thanks to how!!'s refactoring prowess, company profits are up!

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

how!! posted:

If the horror fits on on eline, its not an horror.

Counterpoint:
C# code:
sNoteType = objSelection.Items[1].Selected ? objSelection.Items[0].Selected ? objSelection.Items[3].Selected ? objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " :string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " :string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ?string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "BA " : objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LS " : objSelection.Items[3].Selected ? objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "BA " : objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "FD " : objSelection.Items[0].Selected ? objSelection.Items[3].Selected ? objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "BA " : objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LS " : objSelection.Items[3].Selected ? objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "BA " : objSelection.Items[4].Selected ? objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "LT " : objSelection.Items[5].Selected ? objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty + "EV " : objSelection.Items[2].Selected ? string.Empty + "OV " : string.Empty;

how!!
Nov 19, 2011

by angerbot

JawnV6 posted:

Naw I'm totally sure he'll remember the supply fee discount on small orders in the re-write since's it is adequately documented outside of the code.

Its not documented anywhere, including in the code. Which is why no one is going to miss it if it gets lost in a refactor. As it is now, that code I posted above is completely worthless. It doesn't mater that the code "works". It is completely incomprehensible by anyone except for the person who write that code. The reason why this code is so terrible is largely because the whole thing is using a NoSQL database instead of a proper relational database. So all the data is ridiculously denormalized. Any time you make a change to one data structure, you have to also update all the associated other records. A lot of the complexity you see above is not complexity inherent in the business process, its complexity brought on by poor technical architectural decisions. The business this code belongs too is a house cleaning business. Its not some kind of rocket science simulator.

Code that people understand but the computer doesn't is more valuable than code that the computer understands but people don't.

how!! fucked around with this message at 23:21 on Jan 16, 2013

Cocoa Crispies
Jul 20, 2001

Vehicular Manslaughter!

Pillbug

how!! posted:

Its not documented anywhere, including in the code. Which is why no one is going to miss it if it gets lost in a refactor.

I'm sure any customers that get recurring bills would miss it, but who cares about them when you've got software to refactor delete, right?

Suspicious Dish
Sep 24, 2011

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

how!! posted:

Code that people understand but the computer doesn't is more valuable than code that the computer understands but people don't.

This is one of those dangerous "axioms". "people", here, means "you after five seconds of looking at the code". People can understand it, eventually, and you need to understand it, so you can figure out what it's doing, so you can write its replacement.

Yes, it sucks. But you are here to provide value to the customer, and add features to their web app. Obviously, clear, maintainable code helps achieve this, and spending an hour or two to take those parts that really suck and just make them suck less can be a fun weekend hack. I can already spot some basic transforms I'd do to that code to help make it more clean, and Django and a rewrite is not one of them.

Suspicious Dish fucked around with this message at 23:40 on Jan 16, 2013

Kallikrates
Jul 7, 2002
Pro Lurker

how!! posted:

Its not documented anywhere, including in the code. Which is why no one is going to miss it if it gets lost in a refactor.

Customer: "Last week I bought X and it cost Y, today I bought X and it cost Z....."

how!!
Nov 19, 2011

by angerbot

Suspicious Dish posted:

This is one of those dangerous "axioms". "people", here, means "you after five seconds of looking at the code". People can understand it, eventually, and you need to understand it, so you can figure out what it's doing, so you can write its replacement.

Yes, it sucks. But you are here to provide value to the customer, and add features to their web app. Obviously, clear, maintainable code helps achieve this, and spending an hour or two to take those parts that really suck and just make them suck less can be a fun weekend hack. I can already spot some basic transforms I'd do to that code to help make it more clean, and Django and a rewrite is not one of them.

That'll take just as long as doing a complete re-write. Did you see the code I posted above? Thats 300 lines. How long did it take you to completely understand that code? How long will it take you to understand the remaining 50,000 lines? How long will it take you to implement a software application that books cleaning ladies using proper development techniques?

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
When considering a rewrite of an application it is wise to consider that often 10 percent of the features/requirements of an application are responsible for 90 percent of the complexity in the implementation. This can bite you pretty hard if you glance over an application, implement a useful subset of the functionality you see in a couple hundred lines and then use that to justify a rewrite to "finish off those other minor things". As Suspicious Dish said, one should seek to steadily improve poorly-written codebases rather than throwing them out.

Suspicious Dish
Sep 24, 2011

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

how!! posted:

How long did it take you to completely understand that code? How long will it take you to understand the remaining 50,000 lines?

I got the gist of what it was doing fairly quickly. The intricacies and complexities of cross-cutting concerns will take me longer, but I'd need to understand them anyway in order to provide equivalent functionality in a rewrite anyway, so I can rewrite all of it, or I can rewrite just this function. The latter will take shorter.

Bonfire Lit
Jul 9, 2008

If you're one of the sinners who caused this please unfriend me now.

how!! posted:

That'll take just as long as doing a complete re-write. Did you see the code I posted above? Thats 300 lines. How long did it take you to completely understand that code? How long will it take you to understand the remaining 50,000 lines? How long will it take you to implement a software application that books cleaning ladies using proper development techniques?
Do you have a proper spec for the code? Because if you don't, you'll have to completely understand all 50,300 lines anyway before you can rewrite them.

Edit: Also let's not kid ourselves here and pretend you have a spec that encompasses everything your codebase does, because you don't.

Impotence
Nov 8, 2010
Lipstick Apathy
php:
<?
function cronupdate($currentVersion) {
    // for future update checking
    exec("wget -q -O /tmp/update.txt [url]http://localhost/Forum%20Static%20Files/update.txt[/url]");
    sleep(5);
    if(file_exists("/tmp/update.txt")) {
        $handle = fopen("/tmp/update.txt", "r");$newestVersion = fread($handle, filesize("/tmp/update.txt"));
        fclose($handle);
        $newestVersion = $newestVersion + 0;
        if ($currentVersion < $newestVersion) { echo "NEW VERSION AVAILABLE"; } else {}
    }
}
?>
I.. what

how!!
Nov 19, 2011

by angerbot

Isilkor posted:

Do you have a proper spec for the code? Because if you don't, you'll have to completely understand all 50,300 lines anyway before you can rewrite them.

Edit: Also let's not kid ourselves here and pretend you have a spec that encompasses everything your codebase does, because you don't.

No I don't have the "spec", thats the problem. No one has a spec because one does not exist.

I don't have to under stand all 50,300 lines, I just need to understand the entire business. Theres a difference. Just because the code is 50,3000 lines doesn't mean the company does 50,300 things. This particular company only does like 10 or 15 things. A big misconception people always have is that complex code is always complex because the problems are complex. The code is complex because you're doing work arounds. The work arounds are there because you had to work around other work arounds, etc.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

how!! posted:

I don't have to under stand all 50,300 lines, I just need to understand the entire business.

In any large and/or well-established organization, or in any reasonably complex problem domain, there are going to be really weird rules and requirements that, if you're lucky, a handful of people in the company will understand or even be aware of. You will probably not be one of those people.

You'll rewrite the software according to your imperfect understanding, and within a week you'll have someone in your office saying "Why doesn't it foo the bar when the moon is full and the current millisecond is divisible by 37? It has to do that because of the Kwijybo Act of 1873, otherwise we'll be out of compliance and we'll get fined!"

Somewhere, deep in the bowels of the code you threw out, was a chunk of code that handled it that was written by a consultant in 1997. It was undocumented. It was obscure. No one even knew it was there anymore because the code was functioning properly.

Smugdog Millionaire
Sep 14, 2002

8) Blame Icefrog
how!! you should rewrite that poo poo and prove all these haters wrong.

how!!
Nov 19, 2011

by angerbot

Ithaqua posted:

In any large and/or well-established organization, or in any reasonably complex problem domain, there are going to be really weird rules and requirements that, if you're lucky, a handful of people in the company will understand or even be aware of. You will probably not be one of those people.

You'll rewrite the software according to your imperfect understanding, and within a week you'll have someone in your office saying "Why doesn't it foo the bar when the moon is full and the current millisecond is divisible by 37? It has to do that because of the Kwijybo Act of 1873, otherwise we'll be out of compliance and we'll get fined!"

Somewhere, deep in the bowels of the code you threw out, was a chunk of code that handled it that was written by a consultant in 1997. It was undocumented. It was obscure. No one even knew it was there anymore because the code was functioning properly.

The real problem was that your Kwijybo Act of 1873 code was so hidden and unknown to begin with. The fact that my theoretical refactor broke it and resulted in a fine is actually a good thing. At least now we can re-implement the Kwijybo Act of 1873 code, and this time we can do it so that its comprehensible and documented. The fine we had to pay is the price it costs to improve the business. Maybe the original Kwijybo Act of 1873 code was buggy and was resulting in us paying more in [whatever Kwijybo Act of 1873 does].

It kind of reminds me of all those companies still using IE6. When IE7 came out, they made a deliberate decision to not upgrade because (most likely) it would require some code that no one could understand to be rewritten. Those companies are now stuck on IE6 forever. In 20 years, those same companies will still be on IE6, because code that is not understood today, will still be not understood long into the future.

MononcQc
May 29, 2007

how!! posted:

No I don't have the "spec", thats the problem. No one has a spec because one does not exist.

I don't have to under stand all 50,300 lines, I just need to understand the entire business. Theres a difference. Just because the code is 50,3000 lines doesn't mean the company does 50,300 things. This particular company only does like 10 or 15 things. A big misconception people always have is that complex code is always complex because the problems are complex. The code is complex because you're doing work arounds. The work arounds are there because you had to work around other work arounds, etc.

A big misconception people often have is that a big picture understanding is as valid as a complete understanding when it comes to getting abstractions right.

There are hierarchical levels of organization to code or information in general. You can think of complexity as a branching tree, where each node you inspect reveals more details you can explore. Lack of abstraction may make such a tree to flat to be internalized and understood. For example, if I wanted to become some guru of everything some company does:

code:
                    [company's stack]----------------.
                   /        |        \                \-[humans, team]
       [web server]     [web app]     [database]---.
      /     |               |         |       \     \
config   implementation    /|\     management  app impl
                   .------' | '-------.
    [business rules]   [framework]    [language]
    /      |      \     /   |   \      /    |   \
  ...     ...    ...   ... ...  ...  ...   ...  ...
And so forth. One can't say they are a guru of the company's stack until they get to know most of the leaves in such a tree. Specialists can know a subtree very well, generalists can know things at a more shallow level. This tree can be subdivided more if you want.

A flat level of organization makes it very hard for someone to focus on any single category at once, understand it, and be able to modify it. Code, documentation, and whatever, can all be reorganized and routinely cleaned up to present cleaner abstraction whether they're classes, modules, high-level concepts, functions, chapters of documentation or whatever.

If we imagine the tree as being purely about code, each of the leaves can be a pure piece of poo poo, it will still be somewhat maintainable and repairable if things are isolated enough that someone can focus on any of these at once, as a unit, gain expertise, and keep working with it. That's very basic stuff in terms of understanding abstraction and isolation of concerns. Problems happen when you need to break that neat structure because of new changes. Then it becomes harder and harder to fix anything without gaining more external knowledge than the topic at hand.

Advocating that a high-level understanding of the code, that just getting to know one shallow aspect of things, is enough to rewrite it all is generally a very bad idea. It means you're taking what could be the skeleton of the tree and say "I can just fill in all the blanks really easily as long as I know the general structure". This is rarely the case, and in fact, re-engineering, or rewriting an application without knowing enough about what it does in details is a risky thing where you're likely to fall in the same trap of having picked the wrong structure, being short on time, and then needing to work around your design.

If, on the other hand, you know what the code does, understand the initial abstraction and why it's broken, then it becomes easier to reorganize it the right way. Rewriting code without understanding what it does is a surefire way to shoot yourself in the foot.

how!!
Nov 19, 2011

by angerbot

Smugdog Millionaire posted:

how!! you should rewrite that poo poo and prove all these haters wrong.

"These haters they gon' hate on you like anyway" -gucci mane

Damiya
Jul 3, 2012

how!! posted:

The fact that my theoretical refactor broke it and resulted in a fine is actually a good thing.

Maybe the original Kwijybo Act of 1873 code was buggy and was resulting in us paying more in [whatever Kwijybo Act of 1873 does].

So your theoretical refactor is theoretically a good thing because it costs your company money to theoretically fix a theoretical problem that might not even theoretically exist.

Please inform any employer that you feel this is the way it is before they hire you.

X-BUM-RAIDER-X
May 7, 2008

how!! posted:

No I don't have the "spec", thats the problem. No one has a spec because one does not exist.

I don't have to under stand all 50,300 lines, I just need to understand the entire business. Theres a difference. Just because the code is 50,3000 lines doesn't mean the company does 50,300 things. This particular company only does like 10 or 15 things. A big misconception people always have is that complex code is always complex because the problems are complex. The code is complex because you're doing work arounds. The work arounds are there because you had to work around other work arounds, etc.

I don't know if you're trolling or not because I don't see how an actual person who claims to be a software engineer can be this dumb, but admitting you don't understand 50000 lines of code and using that as a lame excuse to rewrite it is terrible. I mean are you claiming to know all of the built up knowledge (bug fixing and the like) involved in maintaining that code? I don't even know why I'm asking this question. I'm sorry not all solutions to problems are as elegant as you'd like them to be but every other person in the world does just fine. Perhaps get some therapy?

MononcQc
May 29, 2007

Damiya posted:

So your theoretical refactor is theoretically a good thing because it costs your company money to theoretically fix a theoretical problem that might not even theoretically exist.

Please inform any employer that you feel this is the way it is before they hire you.

In an interview, how!! asks you if you value your code. If you do, he won't work for you because he won't be able to rewrite it in lieu of reading it to understand it.

MononcQc
May 29, 2007

When traveling, how!! brings a white sheet of paper and draws the map as he goes, because "there are way too many lines" on those that exist.

Hamled
Sep 11, 2003
I once threw out an entire authentication system because it was an undocumented, unreadable piece of poo poo and I suspected it was full of bugs and security holes and other nasty poo poo. It turned out that we did actually use that system to allow users to log in.

We lost an entire month of revenue while I rewrote the thing using clean, well-documented, understandable code that resembled none of that ugly spaghetti code we had previously. We still haven't gotten our user base back to what it had been. And to make things worse, two months later some rear end in a top hat hacker found a SQL injection exploit and ended up stealing our entire authentication database.





Just the cost of improving our business, I guess.

Suspicious Dish
Sep 24, 2011

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

how!! posted:

The real problem was that your Kwijybo Act of 1873 code was so hidden and unknown to begin with. The fact that my theoretical refactor broke it and resulted in a fine is actually a good thing. At least now we can re-implement the Kwijybo Act of 1873 code, and this time we can do it so that its comprehensible and documented. The fine we had to pay is the price it costs to improve the business. Maybe the original Kwijybo Act of 1873 code was buggy and was resulting in us paying more in [whatever Kwijybo Act of 1873 does].

EOF >> how_quotes.tzt

The code wasn't hidden and unknown. You never bothered to read the very minor 300 lines in the first place to figure it out, because "oh man this is so complex".

how!! posted:

It kind of reminds me of all those companies still using IE6. When IE7 came out, they made a deliberate decision to not upgrade because (most likely) it would require some code that no one could understand to be rewritten. Those companies are now stuck on IE6 forever. In 20 years, those same companies will still be on IE6, because code that is not understood today, will still be not understood long into the future.

It's not because they don't understand the code, in most cases it's because they bought some cheap CMS from a company that went out of business in 1996 and they don't even have the code.

Zamujasa
Oct 27, 2010



Bread Liar

Biowarfare posted:

php:
<?
function cronupdate($currentVersion) {
    // for future update checking
    exec("wget -q -O /tmp/update.txt [url]http://localhost/Forum%20Static%20Files/update.txt[/url]");
    sleep(5);
    if(file_exists("/tmp/update.txt")) {
        $handle = fopen("/tmp/update.txt", "r");$newestVersion = fread($handle, filesize("/tmp/update.txt"));
        fclose($handle);
        $newestVersion = $newestVersion + 0;
        if ($currentVersion < $newestVersion) { echo "NEW VERSION AVAILABLE"; } else {}
    }
}
?>
I.. what

Reminds me of a similar script from a prior company. Hosted client sites (all on the same network at the time, mind) accessed a public PHP page on the main company website that dumped out all the rows of a database table. It then dropped its entire table and replaced it with the downloaded data. Over 10 MB of data each time, in plain text, every day.

The data was for patterns to match e-mail bounce messages and changed about once a quarter.

how!!
Nov 19, 2011

by angerbot

Damiya posted:

So your theoretical refactor is theoretically a good thing because it costs your company money to theoretically fix a theoretical problem that might not even theoretically exist.

Please inform any employer that you feel this is the way it is before they hire you.

Hows that any different than a new manager coming on board and noticing that %0.13 is being shaved off all transactions. He asks the programmers why that is. None of the programmers have any idea. Three days later a programmer finds that on line 63463 theres a bit of code that subtracts %0.13 off all transactions. Manager asks why it is doing that. Programmer has no idea. No other manager has any idea. Manager tells programmer to remove that code. Company is then fined. I call it How!!'s rule of software complexity: As software complexity increases, bugs and features become indistinguishable.

(USER WAS PUT ON PROBATION FOR THIS POST)

Smugdog Millionaire
Sep 14, 2002

8) Blame Icefrog
Rewriting code because you don't understand it may not quite be as insane as it sounds. I read a Kent Beck blog post (I think, could've been some other notable person) wherein he claimed that refactoring was a useful technique he used to understand new codebases: he'd take a look at existing code and refactor it until he understood it. But of course he doesn't destroy 100% of the functionality in the process.

Null Pointer
May 20, 2004

Oh no!

how!! posted:

The fact that my theoretical refactor broke it and resulted in a fine is actually a good thing. At least now we can re-implement the Kwijybo Act of 1873 code, and this time we can do it so that its comprehensible and documented. The fine we had to pay is the price it costs to improve the business.
Warning: the programming advice contained herein will most likely get you fired/sued/prosecuted.

Adbot
ADBOT LOVES YOU

Damiya
Jul 3, 2012

how!! posted:

I call it How!!'s rule of software complexity: As software complexity increases, bugs and features become indistinguishable.

:allears:

Smugdog Millionaire posted:

Rewriting code because you don't understand it may not quite be as insane as it sounds. I read a Kent Beck blog post (I think, could've been some other notable person) wherein he claimed that refactoring was a useful technique he used to understand new codebases: he'd take a look at existing code and refactor it until he understood it. But of course he doesn't destroy 100% of the functionality in the process.

That bold bit is the key point; there's a difference between refactoring and rewriting.

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