Open Side Menu Go to the Top

01-18-2013 , 09:19 PM
The story of a carpenter looking for work:

http://www.jasonbock.net/jb/Default....a6506e2f35eaac
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **
$25m Guaranteed WPM on CoinPoker
Join the action now
Daily Rewards • Splash Pots • CoinRaces
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **
01-18-2013 , 09:27 PM
Quote:
Originally Posted by Neil S
The story of a carpenter looking for work:

http://www.jasonbock.net/jb/Default....a6506e2f35eaac
how smart can that carpenter be, if he doesn't even know how to play a simple social game? i think the interviewer made the right choice.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-18-2013 , 09:57 PM
Quote:
Originally Posted by Neil S
The story of a carpenter looking for work:

http://www.jasonbock.net/jb/Default....a6506e2f35eaac
I was a carpenter throughout much of my 20s. This interview would have been no different than a real interview if he changed a few words.

There can be subtle differences between working with various woods. Redwood, for example, is not very good to build certain items with because it tends to dry then twist into odd shapes.

And yes, they will judge you quite a bit on the brand of tools you use. Craftsman is like the VBScript of carpentry.

And don't even get me started on the **** painters will ask you...
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-18-2013 , 11:19 PM
Quote:
Originally Posted by gaming_mouse
how smart can that carpenter be, if he doesn't even know how to play a simple social game? i think the interviewer made the right choice.
lol wat

are you hiring social experts or carpentry experts?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-18-2013 , 11:25 PM
Quote:
Originally Posted by greg nice
lol wat

are you hiring social experts or carpentry experts?
i'm hiring socially un******ed people. oh and also people who can get simple jokes :P
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 04:59 AM
daveT style post coming. Just warning you.

Let's look at a couple of concrete examples of what we're talking about here:

Example 1: You and a co-worker are building a new feature for your web site that has two pages. Before starting you talk it over and think that the two pages will be pretty independent so you each just do one of them. You each take a day to do your work but your co-worker finishes his page a little bit before you and pushes his work. You pull his changes down and realize that you can actually see a common theme in both pages that could be extracted and shared. Your best guess is that it would take 3-4 hours to do this (refactor the code, update tests, and write some new tests). Do you do it?

To me this seems like a no brainer. You mention to your co-worker your thoughts, maybe leave a note in the code, and then leave it for when you add a third page or a new feature that's going to require you to modify the code. But making that change right away is silly because:

1. It takes time - both duration and effort.
2. You don't know if people are going to use your new feature. You might be spending time fixing code that nobody is going to use or that needs to be totally thrown out and re-written as a significantly different feature.
3. When you add the next page/feature you're going to know more about your code and be able to plan/do a better refactoring at that point then you could do now.

This kind of refactoring, where you're detecting patterns in your code/application, is super common. But if you're religiously trying to keep your code in 'perfect' shape you're probably going to be finding and extracting WAY too many patterns. It's similar to over fitting a data set when doing machine learning.


Example 2: You have a sad life maintaining a big financial companies legacy system with little to no automated tests. There's a bug where the date displays poorly formatted (let's say missing a space) and for whatever reason the big boss man wants it fixed now after living with it for 35 years. Once you get into the code you realize that there's sort-of-complex code for displaying the date and that its duplicated every time the date is displayed. You realize that the best approach is to create a common date formatting function/class and have it called every time the date is to be displayed. Do you update all the code?

Again, this seems like a no brainer to me. The added work of trying to make this change the right way (both in development time and testing time), the increased risk of ****ing up some other part of the app, and the low chance of needing to do future date change bug fixes/features means that I'd probably just add the space and move on with my miserable life (Maybe I add the common date formatting function/class). If I find that I'm getting multiple requests to fix date issues then I'll re-evaluate and probably improve the whole system.


Example 3: You're building a web site where you need to do some daily processing on users - something like if a user has performed 1 of 10 possible actions you want to send them an email. You realize that the right way to do this is to probably mark users when they perform these actions and then have your job go over the marked users. But you also realize that will take touching a bunch of code and for a lot less time you could just write a not-too-complex query that just looks at all users every day and checks if they've performed an action you care about. You do a quick test and realize that'll probably work ok until you get a couple of million active users.

If this is me I'm going to use the not-super-scalable approach, write a comment in the code about the results of my quick-n-dirty test, and hope that some day I'm going to have to refactor/rewrite the job because I have a couple of million active users.

These sorts of poor-performance but easy-to-write cases come up fairly often and when you're going to have a gradual decay of performance that is fairly visible (in the above example you'll gradually see the daily job take longer and longer as you get more users) it often makes sense to take the easy route.


So in each case we avoid the refactoring necessary to make 'perfect' code and incur some technical debt because there's a significant chance that the time we spend on the refactoring or writing great code won't actually save us time in the end.


As for:

Quote:
Originally Posted by Shoe Lace
How about going back into a 3,500 line file from 1.5 years ago that has php/mysql/html/js all mixed in as well as in-line style tags littered everywhere and of course most of the JS events are attached directly to the elements in-line.

Then imagine stuff on that page depends on data from 3-4 other pages and you also have 8 other files in the 1-3k line range filled with the above bad coding decisions.

All of that starts from "hey, it's only 1 style tag" or "whatever, I want to improve my hourly by just finishing this and moving on". They destroy you later though. That is technical debt.

This is as stupid as saying:

"How about getting a $10,000 credit card bill? This all starts with 'Hey, it is only 1 pair of shoes that cost $100'. They destroy you later though. This is debt." And using that as an argument that someone that needs shoes shouldn't pay for them with a credit card.

As a totally unrelated aside, I think there's a lot of doubt about the broken windows effect on crime in real life.

Quote:
Originally Posted by gaming_mouse
Of course, as stated, that is true. The point is that, as a matter of experience (certainly in my case, ymmv) -- it is almost always the case that when you sacrifice the means (good quality code) you will, in fact, not meet your ends. And the aphorism you are invoking, which sounds so reasonable one cannot argue against it, is in practice usually a rationale for making bad choices.
Nobody is saying you shouldn't write good quality code. As for the rest, I hope I can continue to never have to work with people that need rules like "never introduce technical debt!" to avoid being lazy. Of course its also kind of ridiculous to think that a phrase or rule like that would have any effect on code quality since lazy programmers are going to be lazy regardless. (Basically what candybar said)

Quote:
Originally Posted by greg nice
jj/Neil are coming from the business end perspective

most others from the code hacker perspective
I bring the same perspective to my personal projects. If anything I'd say that the divide is what someone else said: Those that believe code is a means to an end vs. those that think the code itself is really important. Even when I do a personal project I'm usually trying to get something out of my code as opposed to just writing code for the sake of writing code so I'm going to do what I think is the most efficient way of getting what I want done - done.

Quote:
Originally Posted by greg nice
yeah perhaps its best to have the programmers strive for great code, and the managers striving for speed of release, and ideally a balance is achieved somewhere in the middle
This seems like a ****ty work environment. I want to work with/for people that are professional and competent enough to make these kinds of decisions without needing a management structure in place. I don't understand why smart programmers can't understand basic business goals and make decisions based on tradeoffs that include non-technical pros and cons.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 05:11 AM
Quote:
Originally Posted by tyler_cracker
shabby,

were you the one who threatened to start a thread about how different posters' styles closely reflect their professional experience? cuz i think this last topic contains some great examples.
I was. I thought about it a bit and what I'd like to do is come up with a small survey of different programming scenarios (some like the examples in my above post, some like "would you use jquery", etc.) and also a couple of broad background questions (education background, years experience, biggest company you worked for, etc.).

But realistically it seems like a lot of work, I'm lazy, and I'm pretty busy right now. So if some one else wants to do it or has another idea for the topic I think it would be super interesting - so go ahead and do it.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 06:46 AM
v good examples
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 08:55 AM
Quote:
This kind of refactoring, where you're detecting patterns in your code/application, is super common. But if you're religiously trying to keep your code in 'perfect' shape you're probably going to be finding and extracting WAY too many patterns. It's similar to over fitting a data set when doing machine learning.
Refactoring if not done properly can set you back quite a bit. It becomes riskier if done informally and adhoc. You start digging in the code and discover opportunities to change, you dig deeper. The more you dig the more you turn up...eventually you dig yourself into a hole. To avoid this you should refactor systematically.

That's pretty much the content of the preface of "Refactoring" by Fowler. So in essence the idea of refactoring is if you do it right you avoid exactly the "over fitting" that you describe.

The "flag to refactor later" seems like a really, really bad practice. It's like TODO: xxx comments in code. Chances are that that stuff will never actually be done.

I'm also wondering why the coworkers from example 1 weren't pair programming.

Quote:
Again, this seems like a no brainer to me. The added work of trying to make this change the right way (both in development time and testing time), the increased risk of ****ing up some other part of the app, and the low chance of needing to do future date change bug fixes/features means that I'd probably just add the space and move on with my miserable life (Maybe I add the common date formatting function/class). If I find that I'm getting multiple requests to fix date issues then I'll re-evaluate and probably improve the whole system.
The first thing you should do is write tests that reproduce the bug and add some extra tests for other corner/special cases you can think of imo. Quickfix+do later is certainly not what I'd expect. Quite frankly if a manager gives you grief if you suggest this needs to be untangled and improved he's doing his job wrong (imo)

Since my background is both in programming and management (+academics now) I actually have pretty strong opinions on this topic. Code quality matters, be religious about it...profit will follow. The most important thing is (always) to solve customer problems/make their life better. Your software is a means to that end BUT it's really hard to rush to the help of a customer if a metal chain of complex code is wrapped around you feet.
As a nice sideffect you are pretty likely to foster an awesome culture and attract good programmers.

Quote:
These sorts of poor-performance but easy-to-write cases come up fairly often and when you're going to have a gradual decay of performance that is fairly visible (in the above example you'll gradually see the daily job take longer and longer as you get more users) it often makes sense to take the easy route.
Maybe I'm a bit biased because I mostly worked on fairly complex software (ERP) but pretty much every major headache we ever faced was rooted in something starting like this and escalating.
Your argument is "well we often don't have the time, would rather handle improtant customer issues now". Guess how much time you'll have when some major desing flaw and/or bugs get exposed later.

tl;dr: Fix it now or you won't fix it later. It's kind of human nature if we don't do something right away and "get away with it" we are extremly unlikely to ever do it later.

Quote:
So in each case we avoid the refactoring necessary to make 'perfect' code and incur some technical debt because there's a significant chance that the time we spend on the refactoring or writing great code won't actually save us time in the end.
I guess this is exactly where we disagree. I think it's very likely people underestimate the consequences of "coderot" and you think I'm overly carefull/wasting valuable time

Quote:
Nobody is saying you shouldn't write good quality code. As for the rest, I hope I can continue to never have to work with people that need rules like "never introduce technical debt!" to avoid being lazy. Of course its also kind of ridiculous to think that a phrase or rule like that would have any effect on code quality since lazy programmers are going to be lazy regardless. (Basically what candybar said)
Right that's why it shouldn't be a phrase like that. It's basically company strategy and you use stories to make it concrete. An abstract rule like that is pretty worthless as a strategy.

Last edited by clowntable; 01-19-2013 at 09:19 AM.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 10:17 AM
Quote:
Originally Posted by clowntable
I'm also wondering why the coworkers from example 1 weren't pair programming.
Oh good lord...

Edit: Actually that's kind of my response to your whole post. I'm starting to think there's an interview question in here I want to ask to make sure we never hire anyone that thinks like this.

I mean where do you draw the line clowntable? Do your generic platitudes about how debt costs you more time/effort have any boundaries? If you're writing an algorithm to do something do you always spend days researching to make sure you have the optimal solution? Is it ok to write an algorithm that only breaks at Facebook scale? At 1/2 Facebook scale?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 01:47 PM
Quote:
This is as stupid as saying:

"How about getting a $10,000 credit card bill? This all starts with 'Hey, it is only 1 pair of shoes that cost $100'. They destroy you later though. This is debt." And using that as an argument that someone that needs shoes shouldn't pay for them with a credit card.
You can't make an analogy like this, it has no relation to the thing being discussed.

Also in your #2 example I think you just need to use your OS or editor better because replacing let's say 250 instances of some date function with custom formatting with 1 wrapped function that sets the date+formatting is really just a find/replace operation on your code base while introducing 1 new function.

At worst you have to include a new resource into key files but that can also be solved by find/replace very painlessly and realistically you probably wouldn't need this step but it's a non-issue even if you did.

#1 is also pretty similar. If it takes you 4 hour solid to refactor a day's worth of coding then something is seriously wrong.

#3 (and even #1) both sound like you made a serious flaw in the core of your application design. It should be really simple to do what you want in #3 if things are decoupled.

I actually made a change like this in a pset from an introduction CS course and it took literally 5 minutes to add event-like triggers to half a dozen areas of the application and the rest of the time was spent writing a function that dealt with what that event needed to do. The size of each of those areas of the app do not even matter too, that's the benefit of writing code that isn't rushed garbage.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 02:59 PM
shabby,

i refactor 1 right now, though i'm willing to concede that it could wait. a website with two pages is a different animal from a thriving website, so refactoring now might be premature optimization.

i had the same thought as clown about pair programming here -- if not for the initial work, then a very quick pairing for the pull-the-common-stuff-out refactor.

i'm with you on 3. rearchitecture is not refactoring, the "correct" solution sounds like a lot of work for little perceivable gain (it's not like your mark-and-sweep approach is "wrong"), and we may never grow to the point where we need the more advanced solution.

i think you're very, very wrong about 2. i refuse to touch a single line of your giant legacy application without tests to pin down the existing behavior and tell me when i've introduced a regression. if my boss can't handle that, she should find an intern to do monkey work and move me to a different project.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 03:01 PM
Quote:
Originally Posted by Shoe Lace
I think you just need to use your OS or editor better because replacing let's say 250 instances of some date function with custom formatting with 1 wrapped function that sets the date+formatting is really just a find/replace operation on your code base while introducing 1 new function.
Quote:
If it takes you 4 hour solid to refactor a day's worth of coding then something is seriously wrong.
you're so adorable!

Last edited by tyler_cracker; 01-19-2013 at 03:08 PM. Reason: hint: the mechanics of manipulating the code are not what takes 4 hours
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 03:14 PM
Quote:
Originally Posted by tyler_cracker
i think you're very, very wrong about 2. i refuse to touch a single line of your giant legacy application without tests to pin down the existing behavior and tell me when i've introduced a regression. if my boss can't handle that, she should find an intern to do monkey work and move me to a different project.
A little more about what I was thinking with this one (actually based on a bug I had once). I was thinking a lot of complex-but-not-quite-the-same date logic throughout the app (hence the reason we're not talking just grepping code). Something along the lines of sometimes looking at a user's location for time zones, sometimes using 24 hour time, etc.

And even in my simple fix - I would still write a test for the code that I'm fixing. I'm just not tackling any of the other date-related tech debt.

Edit: This is why arguing with programmers on the internet is the worst - I keep wanting/needing to clarify stuff. This is a perfect example of what I mean when I say I'm not talking about bad coding when I'm talking about acceptable tech debt. Fixing a bug without a test, in the majority of cases, is just bad coding. I didn't mention the test because that's just part of fixing the bug.

Last edited by jjshabado; 01-19-2013 at 03:33 PM.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 03:16 PM
Quote:
Originally Posted by tyler_cracker
shabby,

i refactor 1 right now, though i'm willing to concede that it could wait. a website with two pages is a different animal from a thriving website, so refactoring now might be premature optimization.

i had the same thought as clown about pair programming here -- if not for the initial work, then a very quick pairing for the pull-the-common-stuff-out refactor.
Note that the fact that its two people isn't really that relevant anyway. I (and I assume many other people) have written two things and not really realized until I stepped back at the end that there was a better way to do that.

Pair programming is a whole other debate. Maybe useful but by no means a guaranteed better solution.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 03:21 PM
Quote:
Originally Posted by Shoe Lace
#3 (and even #1) both sound like you made a serious flaw in the core of your application design. It should be really simple to do what you want in #3 if things are decoupled.

I actually made a change like this in a pset from an introduction CS course and it took literally 5 minutes to add event-like triggers to half a dozen areas of the application and the rest of the time was spent writing a function that dealt with what that event needed to do. The size of each of those areas of the app do not even matter too, that's the benefit of writing code that isn't rushed garbage.
Lol, if you're wondering why I don't take you seriously its because of comments like this.

Edit: And the one about it being trivial to replace lots of pieces of a big legacy system.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 04:30 PM
Quote:
Originally Posted by jjshabado
Lol, if you're wondering why I don't take you seriously its because of comments like this.

Edit: And the one about it being trivial to replace lots of pieces of a big legacy system.
That statement is really funny to me because that can only mean 1 of 2 things, or perhaps it's a combination of both?

1. You don't trust your OS or editor.

or...

2. You don't know what a function does.

If I replace (incoming pseudo code):

Code:
date(user.created, "mm:dd:yyyy")
with...

Code:
niceDate(user.created)
Assuming niceDate returns exactly:

Code:
date(user.created, "mm:dd:yyyy")
Then nothing actually changes UNLESS my OS or editor (whatever you use to do the replacing) is broken.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 05:00 PM
In the interest of not being a total ass - I don't take you seriously because you still don't seem to get what you're missing. Your assumptions aren't realistic.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 05:06 PM
It's a good thing bugs only show up when something is actually changed, or that kind of find and replace would be dangerous.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 05:57 PM
Pretty much agree with everything jjshabado wrote in the past few posts.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 06:47 PM
Quote:
Originally Posted by Shoe Lace
That statement is really funny to me because that can only mean 1 of 2 things, or perhaps it's a combination of both?

1. You don't trust your OS or editor.

or...

2. You don't know what a function does.

If I replace (incoming pseudo code):

Code:
date(user.created, "mm:dd:yyyy")
with...

Code:
niceDate(user.created)
Assuming niceDate returns exactly:

Code:
date(user.created, "mm:dd:yyyy")
Then nothing actually changes UNLESS my OS or editor (whatever you use to do the replacing) is broken.
Aside from what jjshabado said (about this kind of example not being relevant and a sign of not having encountered complex issues in large code bases), I'd also point out that for most applications, this instance of "refactoring" is harmful. In part because your code is worse, but also because you're wasting energy on the wrong things. You're replacing a call to a well-understood multi-purpose function into a call to a poorly-understood single-purpose function. This isn't abstraction - taken to an extreme, this is obfuscation. If you replaced a call to a standard function f(a, c) with my_f(a) any time you noticed you also did f(b, c), f(d, c), etc, you'd be creating a lot of ridiculous functions.

What do we do then? It's important to realize that your function isn't abstracting logic - it's abstracting a constant argument. There's no need to create a function where a constant would do:

date(user.created, app.constants.globalDateFormat)

Also, understand that minor repetition is often incidental. If the repeated parts are likely to change independently, you don't have real repetition and trying to abstract it away only impedes changes in the future. If the repeated parts are not likely to change at all, it's probably irrelevant what you do. It's when repeated parts are likely to change together that abstraction becomes meaningfully useful.

In most cases, unrelated calls to date function that happen to have the same format argument are often not real repetition.

Too many programmers, when they try too hard to write "good code" as opposed to simply solve problems, focus on ridiculous things like this and as a result write worse code. I've seen programmers eagerly duplicate the entire system/library interface with a "wrapper" with a much worse designed interface (in part because of his own limited use case, in part because library/system developers are much better programmers and API designers than he is) because supposedly that makes his code more portable, when in fact you're now dependent on a poorly designed, poorly maintained one-man project by a bad programmer instead of a widely-used, stable abstraction.

Real engineering problems are difficult and require much more thinking. For one common instance, you may have two complex components that have built different interfaces and implementations that were originally designed for different purposes, but over time, have converged in terms of requirements and dependencies, yet the interface is different enough that you cannot easily point users of one component to the other. Users of the same component can easily communicate with each other, but not with users of the other. There are new feature requests that require that users of these two different components easily communicate with each other. It's likely that down the road, having a single component will be ideal. What do you do?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 06:47 PM
Quote:
Originally Posted by jjshabado
In the interest of not being a total ass - I don't take you seriously because you still don't seem to get what you're missing. Your assumptions aren't realistic.
Do you have any proof or facts to add in or do you think "assumptions aren't realistic" is good enough? How do you expect people to respond to that?

You make all these claims but instead of talk about the things you're trying to discuss you use completely crippled analogies or just end things on random babbling when people don't agree with you.

When you learn how to debate a topic that isn't at the 3rd grade level I'll consider replying to you.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 06:54 PM
@candybar,

I'm guessing you didn't read jj's post? He came up with the situation, not me. He also didn't make it clear how the date was being formatted in those many spots. He just mentioned it was somewhat complex and wanted to move it into 1 function.

Heck, he even specifically said to make a function for it because it was determined to be the best idea.

Quote:
You realize that the best approach is to create a common date formatting function/class and have it called every time the date is to be displayed.
When reading that I made an assumption that the best possible solution to the problem was to create a function to wrap the data. How else can you possibly parse "create a common date formatting function"?

Sometimes I have to pinch myself when reading this forum to make sure it's real life.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 06:55 PM
candybar,

that was a good post and i agree with most of it. and while your point about the advantages of using a known library stands, i do think

niceDate(user.created)

reads much better than:

date(user.created, app.constants.globalDateFormat)
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
01-19-2013 , 06:59 PM
jj,

nice work bringing the conversation back to earth with examples -- they are interesting cases where a case could be made for both sides, but i think in the real world i'd be likely to agree with your approach in them. i do think it would be surprising to have 2 web pages that took a day to build and would take half a day to refactor. but again, it would all depend on a specific example...
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **
$25m Guaranteed WPM on CoinPoker
Join the action now
Daily Rewards • Splash Pots • CoinRaces
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

      
m