The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years
-
Strap
onin, this is gonna be a long one.A quick recap for those of you who have joined in my absence:
My last job was a disaster area. Working for the company in and of itself wasn't bad, but like many small companies, no one actually knew what the hell it was I did and I ended getting tasked with a lot of responsibilities that I really wasn't qualified for. I was "the computer guy" and eventually was expected to fix anything that blinked, beeped, or even had a button on it (I posted about this occasionally way back in the days of Community Server blowing goats). I eventually left for my current job.
Which is a hell of a lot better. There is an actual dev team with IT being separate, we use version control properly, we have code reviews, we (mostly) do Agile with sprints and retrospectives and story pointing and all of that fun stuff. It's still a small-ish company, but it's bigger than my last one and has overall been a much better experience.
I was hired to work on the web team, which was re-writing the website in the latest and greatest buzzword laden stack you could imagine. TypeScript, Knockout, MVC, MVVM, Less, you name it, if it was hot we threw it in there. A few months after I was hired, there was an open call for anyone who wanted to get cross-trained on our internal, desktop software. I thought to myself, "sure, getting cross trained is almost never a bad thing and I can learn some new stuff on the way" so I signed up.
It was exactly like internal legacy software most of us have worked on at some point or another. The UI was Winforms. The DAL was half Entity Framework and half some custom ORM a contractor had created years ago. One of the internal namespaces had a typo that had never been fixed. There was one specific form that had a code-behind file of something like 12k LOC and was backed by a stored procedure to match. Data imports were handled by SSIS. There was even a dusty, dark little corner of the application that was written in VB6 that no one liked to talk about but it was stable and, as such, wasn't going anywhere.
So for a few sprints I bounced back and forth between the hot new sexiness and the old tired dog. Until business decided that the company needed more developers working on the legacy system, and I had already started training on it so I was going to stay there indefinitely. I was not consulted on this decision. But whatever, it's still okay. Not the best thing in the world but I can work with it. We worked in a re-factoring/updating story every sprint and slowly but surely we're improving things. We're replacing Winforms components with WPF, we're removing cruft that never should have existed, taking business logic that for some reason was in stored procedures and moving it to a more logical location. It was good. It wasn't great because we still had to support a lot of ugly shit, but things were definitely getting better.
Budget time roles around and we start sketching out a plan for the next year. We're going to get rid of this massive Winforms component that contains way too much logic and drives something like 50% of the UI. We're going to start re-designing smaller forms in WPF using MVVM. We're going to cull a lot of deadwood sps that never should've existed in the first place. We're going to put a stake in the heart of VB6. We're finally going to fix that fucking namespace typo. There was a light at the end of the tunnel. We research various 3rd party libraries that we're going to need to buy/get subscriptions for and submit the budget for our team.
(There's an entire product line disaster in here that I'm going to just skip for the sake of brevity (lol yeah right). I might write another post about it later)
Three months later, the company decides that it wants to make part of the internal app available on the website. "I mean, if we've got software over here that does one thing, and software over here that does other things, why can't we just link them up?" Well SSAE-16 audits for one. Also because the in-house app relies on AD authentication, and about a 1,000 other reasons why.
So we scrap the existing plan to slowly upgrade-in-place. What the business wants and when they want it is just something that is not possible with the resources that we have available. We eventually compromise and crap out an API (entirely separate from the legacy application) that does what they want (duplicating code and logic from the existing app). This is sufficient...for now. But they want us to keep building it up, and want to expand this on-line offering significantly. So we abandon our plan for the year. The legacy desktop application will still exist, and it will still serve the purpose of being our main in-house workhorse, and we will still support it, but the majority of our energy will be directed towards porting at least some of it to the web. Well this is not ideal but it could be worse.
Spoilers: it got worse.
Business wants more web features. We need to expand the shitty API that we threw together to meet an impossible deadline. We start brainstorming.
Then disaster hits. (This is probably the time to note - we are a pure MS/.NET shop. Hosted in IIS, db is MS SQL Server. Website is written in TypeScript and C#, etc etc).
The CTO goes on a trip to Rackspace. I don't know exactly what happened (I assume a brain slug attached itself or possibly some sort of severe concussion), but when he came back he issued an edict - "NO MORE WINDOWS DEVELOPMENT". Something to do with Docker and containers.
So now we need to keep our original unrealistic plan but do it in an entirely new tech stack. That no one on our team knows. Yay.
Around this time is where we're told that we are not getting any additional budget beyond what we requested originally, Also yay. Here's a condensed version what I had to say about it in our work chat:
So to recap - we have roughly 9 sprints to rewrite large parts of the application, on a new stack, with a new architecture (including watertight or least minimally leaky devops), with 3 people, and 0 budget. Not to be overly pessimistic but are alarm bells ringing for anyone else?
So that brings us roughly to here. I'm spending most of my time learning Node/Express and Python (which, by the way, seems to be an exceptionally bad language for all of the praise it gets) and re-implementing existing code in new languages, while operating under an insane deadline and creating a ton of technical debt. Dear person who has to maintain this code: I am truly sorry.
-
@mikeTheLiar Welcome back! That sounds perfectly awful.
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
I'm spending most of my time learning Node/Express
Some of us around here know a decent amount about this; feel free to pop by coding help if you need it.
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
The CTO goes on a trip to Rackspace. I don't know exactly what happened (I assume a brain slug attached itself or possibly some sort of severe concussion), but when he came back he issued an edict - "NO MORE WINDOWS DEVELOPMENT". Something to do with Docker and containers.
This is the point in the story where you should tell us you updated your resume.
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
I'm spending most of my time […] re-implementing existing code in new languages, while operating under an insane deadline and creating a ton of technical debt.
Yeah, or you could do that.
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Python (which, by the way, seems to be an exceptionally bad language for all of the praise it gets)
Hm, depends on what you use it for and on your expectations. What are your problems with it?
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Dear person who has to maintain this code: I am truly sorry.
There's an apology thread in the lounge...
-
@asdf said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
What are your problems with it?
Explain this shit (yes I know what's going on here but it's extremely non-intuitive)
C:\Users\MIKE>python Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> l = [[1,2],[3,4]] >>> l *= 3 >>> l [[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]] >>> l[0].append(1e9) >>> l [[1, 2, 1000000000.0], [3, 4], [1, 2, 1000000000.0], [3, 4], [1, 2, 1000000000.0], [3, 4]] >>> t = [(1,2),(3,4)] >>> t *= 3 >>> t [(1, 2), (3, 4), (1, 2), (3, 4), (1, 2), (3, 4)] >>> t[0] += (1e9,) >>> t [(1, 2, 1000000000.0), (3, 4), (1, 2), (3, 4), (1, 2), (3, 4)]
Also,
int
s are immutable? What fucking genius made that decision?
Edit: of and the whole "let's use exceptions as control flow" thing. Reaching the end of an enumerator raises an exception to tell you it's done.
-
Oh and here's a Python 2 vs Python 3 story for you. We were writing abstract classes. Someone accidentally followed a Python 2 tutorial for writing abstract classes. This is totally valid Python 3 code and runs just fine but it completely ignores the "abstract" part of writing abstract classes. See http://stackoverflow.com/q/39029701/1015495
-
@dcon said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Dear person who has to maintain this code: I am truly sorry.
There's an apology thread in the lounge...
Except it's degenerated from the original purpose quite nicely.
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Explain this shit (yes I know what's going on here but it's extremely non-intuitive)
OK, yeah, that's the weird part of Python. 99% of the time, you can just ignore it.
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Also, ints are immutable?
Why is that a problem? They behave exactly the same as in any other language because of that.
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Oh and here's a Python 2 vs Python 3 story for you.
Fortunately, Python 2 is slowly dying. But yeah, you have to be careful which version the website is referring to when looking things up.
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@asdf said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
What are your problems with it?
Explain this shit (yes I know what's going on here but it's extremely non-intuitive)
C:\Users\MIKE>python Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> l = [[1,2],[3,4]] >>> l *= 3 >>> l [[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]]
You created a list of lists, then used the
*=
operator to tell the outer list to repeat all its contents 3 times. As a list is a reference type, you end up with essentially[l1, l2, l1, l2, l1, l2]
.>>> l[0].append(1e9) >>> l [[1, 2, 1000000000.0], [3, 4], [1, 2, 1000000000.0], [3, 4], [1, 2, 1000000000.0], [3, 4]]
You added a value to
l1
, which is in there 3 times.>>> t = [(1,2),(3,4)] >>> t *= 3 >>> t [(1, 2), (3, 4), (1, 2), (3, 4), (1, 2), (3, 4)] >>> t[0] += (1e9,) >>> t [(1, 2, 1000000000.0), (3, 4), (1, 2), (3, 4), (1, 2), (3, 4)]
You concatenated one list with a second list that contains a single item. This operation creates a new list, rather than altering the other one in-place, so now you have
[l4, l2, l1, l2, l1, l2]
.Also,
int
s are immutable? What fucking genius made that decision?Why shouldn't they be?
-
@asdf said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Why is that a problem? They behave exactly the same as in any other language because of that.
i = 5 i += 1
- Create object reference to 5
- Create object reference to 1
- Perform addition
- Store addition in object reference to 6
- Destroy references to 5 and 1
That seems insanely inefficient for such a common operation. Big picture, not that big a deal because we're talking about bytes worth of memory but seriously, why?
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
That seems insanely inefficient for such a common operation.
You're assuming that this is what's actually executed by the CPU. I'm 99.9% sure that's not what actually happens. I mean, C++ compilers might transform the code into SSA form internally, but that doesn't mean they actually create thousands of new variables at runtime.
You're confusing the conceptual level with what actually happens.
-
@masonwheeler said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
You concatenated one list with a second list that contains a single item. This operation creates a new list, rather than altering the other one in-place
Close, but no. The first is a list of lists. Lists are mutable. When you multiply the list, you multiply the references so appending to the first reference appends to all references. The second is a list of tuples. Tuples are immutable so appending to the first reference create and entirely new reference that points to a new tuple. The rest of the tuples remain unchanged.
-
@Tsaukpaetra said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@dcon said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Dear person who has to maintain this code: I am truly sorry.
There's an apology thread in the lounge...
Except it's degenerated from the original purpose quite nicely.
Of course it has. (tho when I posted that, I hadn't realized how much) But it's just as likely the de-degenerate back...
-
Agile is a code word for "we won't bother writing specs".
-
@asdf said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
You're assuming that this is what's actually executed by the CPU.
I have been learning Python for a grand total of about three weeks so I have no idea what I'm talking about. This explanation comes from one of the Pluralsight videos on Python that I watched (Python Fundamentals I believe).
-
@lucas1 Actual quote from my team lead: "we can acquire a budget down the road"
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
We were writing abstract classes.
So I'm going to go out on a limb here and say that the problem is less that Python is a horrible language and more that it's a language that none of you know and doesn't fit your way of thinking. That's not a bad thing either for Python or you, but the suit who figured .NET devs could switch to such a different language really needs to learn some things. One of my coworkers had to make the jump, but a) he chose to and b) I shared a cube with him.
-
@pydsigner I think this is entirely possible.
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
This explanation comes from one of the Pluralsight videos on Python that I watched (Python Fundamentals I believe).
OK, but it still only explains the concept, from a language design POV. The end result is that you can simply use integers like you're used to:
i = 5 j = i i = i + 2 print(j) # would be 7 if integers were mutable in Python, but is 5, i.e. what you expect
BTW: Not sure that this video is a good introductory video if it mentions so many things beginners don't need to know about (how references and mutability actually work in Python).
-
-
@mikeTheLiar That is similar to what I heard yesterday. I feel it is dishonest.
-
@lucas1 said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@mikeTheLiar That is similar to what I heard yesterday. I feel it is dishonest.
Well, to be fair oftentimes they're just passing the dishonesty down. I hear it soothes the guilty consciences or something.
-
@Tsaukpaetra I'd rather do the work for a fair price. That what I do with clients. I probably charge to little because I am too nice.
-
@asdf said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
This explanation comes from one of the Pluralsight videos on Python that I watched (Python Fundamentals I believe).
OK, but it still only explains the concept, from a language design POV. The end result is that you can simply use integers like you're used to:
i = 5 j = i i = i + 2 print(j) # would be 7 if integers were mutable in Python, but is 5, i.e. what you expect
BTW: Not sure that this video is a good introductory video if it mentions so many things beginners don't need to know about (how references and mutability actually work in Python).
@mikeTheLiar If you're fine with reading vs. video you might try the Dive into Python tutorial which is quite good and which I've seen recommended for .NET devs switching to Python.
-
@lucas1 said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@Tsaukpaetra I'd rather do the work for a fair price. That what I do with clients. I probably charge to little because I am too nice.
Yeah, I'm trying to figure out what I should ask for on a certain project myself.
Essentially we're going to be converting a boatload of cascading-reference Google Sheets into a concise web app, but I have NFC what should be the going rate for something like that.
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
I have been learning Python for a grand total of about three weeks so I have no idea what I'm talking about.
Long story short: The only thing you have to remember is:
- There are immutable and mutable types. The latter are always treated as if passed by reference.
- Never create instances of mutable types in default arguments. The resulting behavior will not be what you expect.
Other than that, there should be no practical difference between Python and the languages you're used to.
http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables
(A bit outdated, only the linked paragraph and the following two are relevant.)
-
@Tsaukpaetra I tend to charge less if it is a small business and charge more if it is a big business. Negotiate.
-
@lucas1 said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Negotiate
Problem being: I have no idea how high to start off with, and no reference to how low is too low. ;)
-
@Tsaukpaetra Look at the market rate. If you really want the work, undercut.
I work contract for £300-400 a day, if I was in London I would work £400-600 a day. If I am doing front end stuff i.e. some CSS, HTML responsive I will charge £200 a day and £300 in London ... because London rates are better.
Look at similar professionals in your area and maybe charge a bit less until you get a good rep.
-
@Tsaukpaetra said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
I have no idea how high to start off with, and no reference to how low is too low.
Estimate how much it would cost for the other party to write the same thing from scratch. That's your upper limit. Then estimate your own costs. That's your lower limit.
Look at the market rate, and choose something in between.
-
@asdf said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
estimate your own costs
Time is the tricky one here; you'll want to look at what companies pay for this kind of work, then add back in the overhead for having to do your own benefits, taxes, et cetera.
-
@Yamikuronue Also your own company is also paying you fuck all compared to what they are charging a lot of the time.
-
@lucas1 You definitely want to compare yourself to in-house employees instead. That's the comparison your customers would be doing: hire a guy in vs contract out to a contractor.
-
@Yamikuronue Maybe your customers might, buy you can't. They can't afford to pay for a permie employee forever, they need to have a job done and that needs external resource.
You are taking on considerably more risk doing freelance. Also the customers of <Digital Agency> won't be seeing how much they pay an Employee, they will be paying how much they pay said business.
Contractor will come out slightly cheaper, but then it gets fucked again if there is a recruitment agency involved that will take money off the top.
Whereas Freelance you can keep things cheaper.
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
I'm spending most of my time learning Node/Express and Python
What? Why both?
They both sort of fill the same role. If you're stressed for time, pick one and focus your energy there.
Also, isn't Microsoft now all buddy-buddy with Docker and containers, for their Azure crap? Maybe you can satiate your boss by doing it in their new NET Core thing? Might be easier for a NET shop to move there.
Python (which, by the way, seems to be an exceptionally bad language for all of the praise it gets)
Few languages are actually as good as C#.
What Python and others give you are better ecosystems, OSS and linux friendliness.
-
@Yamikuronue said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Some of us around here know a decent amount about this; feel free to pop by coding help if you need it.
It used to be just @Accalia and me, the node master race.
But now all you peasants started coming in and it's not fun anymore. I've moved back to PHP.
-
@lucas1 Remember, that calculation was to arrive at a minimum: your costs themselves, both in terms of equipment and the value of your time. You always want to aim upwards of that, and only take that price if you are gaining something substantial in terms of non-monetary benefits.
-
@Yamikuronue Thank you for explaining how a business works.
I was talking about a rough estimate about your daily day rate compared to similar individuals ... which is a different thing.
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Explain this shit (yes I know what's going on here but it's extremely non-intuitive)
C:\Users\MIKE>pythonI like how your user name is just MIKE, in capital letters.
I am MIKE. There are many Mikes, but only one MIKE. And that is ME. MIKE!
-
@lucas1 Just helping you keep up with the thread, mate :)
-
@Yamikuronue I was asked about how to charge. I gave a rough estimate based on what I can charge in the UK. I don't see how I wasn't keeping up. In fact I would argue I was giving a more nuanced answer than you.
-
I once had an interviewee critique a stupid Python script I wrote. It printed pseudo-random strings or something. The guy was Polish and had a very shallow grasp of English but he managed go through line by line and explain exactly how terrible the whole thing was. Apparently I'm the world's worst Python programmer. It's ok though, the only Python I write these days is for Sublime Text plugins that I make for myself.
-
@aapis Dude you don't know how much I like talking to programmers where their first language isn't English.
I get really exact answers to question. It takes a while but it is "you can do X", rather than a stream of consciousness. it is kinda like a man page with a voice.
-
@cartman82 said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
What? Why both?
Microservices, baby! We're using node for the more simple CRUD services and Python for the more complicated financial calculations because reasons.
Also, isn't Microsoft now all buddy-buddy with Docker and containers, for their Azure crap? Maybe you can satiate your boss by doing it in their new NET Core thing?
Only in Windows Server 2016 which we don't have. As far as .NET core goes, according to the architect it's "too young". And Mono is "too old".
Filed under: just fucking shoot me
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
Microservices, baby! We're using node for the more simple CRUD services and Python for the more complicated financial calculations because reasons.
Ah, of course! Now it makes sense.
Let us know how it goes!
-
@mikeTheLiar said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
@cartman82 said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
What? Why both?
Microservices, baby! We're using node for the more simple CRUD services and Python for the more complicated financial calculations because reasons.
Reminds me of this: http://ericsink.com/entries/crud.html
-
@lucas1 said in The Story So Far, or what the hell has mikeTheLiar Been Up to for the Past Two Years:
programmers where their first language isn't English.
My first language was BASIC. I've been tainted ever since.
-
@Tsaukpaetra My first language was XBAS BASIC and then BBC BASIC when my granddad (unfortunately RIP) let me use this thing ...
-
@cartman82 you goddamn right
-
@lucas1 Frickin beautiful!