A meta post about negative code reviews
A lot of people seems to have problems whenever I post a code review. The general theme of the comments is mostly along the lines of:
- You are an evil person and a cyber bully to actually do those sort of things and humiliate people.
- You have something against the author of the personally, and you set out to avenge them.
- There is no value in doing a negative code review.
- You never do any good reviews, only bad ones.
- You only tells us what is wrong, but not what is right.
There are a bunch of other stuff, but those are the main points.
For point 1 & 2, I have the same answer:
I talk about the code, not the person. I am actually very careful with my phrasing whenever I do this sort of a review. The code or the architecture is wrong, not the person. There is a difference, and a big one.
For point 3:
Most of those code reviews are generated because someone asks me to do them. And given some of the responses to the posts, I feel that they serve a very good purpose. Here is one such comment. I redacted the project name, because it doesn’t really matter, but the point stands:
I grew up on *** as it was my first layered application, almost 5 years ago and I personally believe that the effort ****** has put into this project during the years is simply amazing. The architecture reflect the most common architectural design patterns and represents almost the concepts expressed by Fowler and Evans. *** is not a project to teach you how to work with Northwind and it is not a project designed exclusively for Nhb. It is designed to show how a layered application should be architected in .NET and there is also a book wrote around this project.
My professional opinioned, backed by over a decade of practical experience and work in the field tells me that the project in question is actually not a good template for an application. And I feel that by pointing out exactly why, I am doing a service to the community.
Look, it is actually quite simple. The major reason that I do those negative code reviews is because I keep seeing the same types of mistakes repeated over and over again at customer sites. And the major reason is that those projects follow best practices as they see it. The problem is that they usually ignore the context of those best practices, so it becomes a horrible mess.
What is worse, there is the issue of the non coding architect, when you have someone that doesn’t actually have responsibility for the output making decisions about how it is going to be built. And those things are actually hard to fight against, precisely because they are considered to be best practices. One of the reasons that I am pointing out the problems in those projects is to serve as a reference point for other people when they need a way to escape the over architecture.
For point 4:
It takes something out of the ordinary to get me to actually post something to the blog. The barrier for a negative code review is how much is annoys me. The barrier for a positive code review is how much it impresses me. It is easier to annoy me to impress me, admittedly, but I quite frequently do good code reviews.
The problem is that most good code bases are actually fairly boring. That is pretty much the definition of a good codebase, of course , so there isn’t really that much to talk about.
For point 5:
That usually come up when I do negative code reviews, “you only show the bad stuff, it doesn’t teach us how to do it right”. Well, that is pretty much the point of a negative code review. To show the bad stuff so you would know how to avoid it. There are literally thousands of posts in this blog, and quite a few of them are actually devoted to discussions on how to do it right. I have very little inclination to repeat that advice again in every post.
Even a blog post must obey the single responsibility principle.
Comments
It is nice that you do not agree to these opinions. Praise does not mean much aside from growing an ego. Critique, on the other hand, is actually useful in learning. I have always preferred being around people who would directly tell when I am doing something stupid. I think it is one of the fastest ways to learn.
Also, these reviews are fun to read, mostly because code is mostly actually WTF-worthy.
While there is value in seeing a "don't do this" post, I think there is greater value in showing how to solve the problem in a better way. In my opinion a code review should not be labelled 'negative' or 'positive'. Isn't any code review about reviewing the code, highlighting any problems you see and showing a better way? And surely the last step is quite important? I appreciate that this blog has lots of coding advice... but if you think the relevant information is easy to find, then it should also be easy to include a link in your post as an example of how you think it should be approached.
Rowen but what "Problem" are you talking about? The Ultimate Problem Of Software Development? If you want to be more specific about the "Problem" you have to find it first - and this is what Ayende is doing. However, I'm not very entertained by this series ... maybe because I'm not the target audience.
Saying "I'm not picking on a person, just their output" doesn't make it any less bullying - don't kid yourself.
Rebecca Black made something which lots of people felt was bad output. Personal attacks would be cyber bullying, but so was "the internet" en masse spamming her with "this output is terrible for these reasons".
The way this post series has gone, the phrases you use, and the fact that you seem to have taken it on yourself to behave this way, all uncalled for - especially when there has been a post made explaining what thoughts went into the codebase, and why it's how it is. You keep these posts coming, despite that, and as people are telling you, even if some points are fair, the overall impression is a very bad one.
@Ayende: To avoid point 5, it would be nice if you would refer to the respective blog post of how to do it right, when you writing about "negative code reviews! This would really help the readers of your blog!
Larz, You do realize that I usually write those blog posts in advance, and that the reply was there because the author got an advance notice, right?
Sincerely I don’t understand why someone would consider this as bullying. This is a personal blog in which from time to time the author expresses his opinions about code. What’s wrong about that? If someone doesn’t agree with a particular review it’s easy to contribute: either by offering their perspective by commenting or linking to a post in their own blog. Personally I find the majority of the posts as very good points for further reflection and discussion. IMHO it’s a pity that the majority of the comments are off-topic and focused on Ayende’s “attitude” rather than being focused on what is being discussed: (just) code.
I agree with Larz, it's not so much what you say but how you say it. You're pretty condescending, past a point that's commonly accepted. You say say it's to the code, and not the person -- but it's people who write the code. Sometimes the bad code is written by good people doing the right thing, but within their limited scope of knowledge. That bad code does not deserve to be lit up in the way that you do.
The bad code that does deserve to be shot at, I think, is when the bad code is a product of a very poor attitude, process, lack of professionalism, wheel reinvention, etc., and it should be blasted. I don't think you have the necessary context to make that determination in many cases.
But you're probably not going to stop, you have earned your reputation. So I guess I say this only for others who think good code reviews require taking personal shots at the "code."
What you are doing is NOT bullying. In the case of the NorthWind project, they guy also wrote a book about Enterprise Architecture, yet he has a code base that many feel is confusing. He is out there as an expert, or at least that's what may be perceived because he is an author. Your critique should be what he deals at his level.
I think some of the negative feedback you are getting is because so many respect you, yet would not feel comfortable being the target of your critique because of your reputation as a great technician. In this case with NorthWind I feel you are warranted in what you say, and you have been fair. Again, the project lead is an author, and should be ready to accept editorial reviews of his book.
First, I enjoy reading your blog as there is frequently information that I can gain value from and learn some new ways to do things. However, these posts sometimes add more "color" to the overall intent which can be seen as directed to the code's author.
"In my last few posts, I have gone over the data access strategy used in NSK. I haven’t been impressed. In fact, I am somewhere between horrified, shocked and amused in the same way you feel when you see a clown slipping on a banana peel. Why do I say that? Let us trace a single call from the front end all the way to the back."
In this example above, your emotions being expressed in this particular review don't add significant value to the review and can give people the impression that you have some issue with the code author. I would suggest taking a second read on these and remove some of this type as a simple statement in the first that you had issues and were going to point them out is sufficient. See the modification below.
"In my last few posts, I have gone over the data access strategy used in NSK. I haven’t been impressed. Why do I say that? Let us trace a single call from the front end all the way to the back."
Removing that one sentence keeps the fact that you are not impressed for the reader without potentially demeaning the author of the code with nonobjective statements.
And as you can see I am trying to follow the points that were being made to indicate what I think needs improvement while also giving an example of how it would be better.
Why do so many of you suck at using your 'written / human communication protocol'? Especially the author. You have the arrogance to pick nits in the logical structures of another's usage of languages and frameworks, while communicating your greatness and attention to detail via malformed English.
Oh, I anticipate some reply about not being your first language. All I ask is for you to examine the ridiculousness of that claim.
Also, @Dave Robbins: Stop being a totalitarian boot-licker. Do you know of some magical 'Enterprise' code-base that the majority of (who, or what was your defined subject in the second segment of your third sentence?) whoever comprises the parent group of 'many'?
Ayende, you're a smart fellow, you can communicate better by applying effort and attention to detail.
I've been learning quite a bit from your reviews. While I disagree on the severity of some points, I really gain a lot from seeing your thought process when analyzing these projects. I think they are a valuable contribution to the community that is missing in a lot of other communities. Please continue doing them.
There's a simple reason why so many people feel offended by your reviews: they want the abstractions, both in code and also in language.
The same way as they simply cannot make a NH call out of the controller action, they also cannot live with someone's saying "hey, this piece of code just sucks". The miss the service layer, the interfaces and of course, the repositories. What they want to here is "well, that's an interesting project and thank you so much, but for this one particular part I would have done it differently...".
I personally find that it has a lot to do with cultural background and while europeans generally tend to be more direct, this is not always the best idea overseas.
It must be allowed to say what is true. I therefore see no problem with those code reviews.
Open source projects, or any framework/platform that publishes their code for all to see, desperately need people to contribute reviews to them to make them better. It also is a way for others to learn the in's and out's of the project so they can plan accordingly if they are forced into using said project ... so keep up the good work, it's an enjoyable read!
Point 5 still stands though.
If you think you have covered the right way to do something that you are criticizing in your negative code review than BY ALL MEANS JUST LINK TO IT!
I don't know where this stupid rule comes from that says that you cannot criticize without providing an alternative. Why should that be the case?
@tobi IMHO rule applies if you are part of the project. If you are on the team you criticism would be better accepted with the suggested alternatives. But if you arfe not involved you can criticize and just do something else. Showing how is just your choice, and Ayende usually do ( or at least he did from more than 5 year since I remember )
"The only people that like to hear that their code is bad are people who are trying to get better." -Giles Bowkett. One of my favorite quotes.
"The barrier for a negative code review is how much is annoys me." Are you still annoyed at the time you write the review? When someone comes across as unduly critical, it's often because of their tone rather than their content. So, eg, from the last review I could pick out a couple of comments that seem emotive ("I mean, seriously") or exaggerated ("infinite levels of indirection" where "unnecessary levels.." would have made the point).
I wonder if that sort of thing makes these posts seem harsher than might be the intent, and distract some reader from the actual points you make.
Nw was such a pile of horrible complexity layered upon layer having such a naive wtf parts in so many places if you zoom in to code - i think you actually went too easy on it. White collar "Enterprise Architects" are one of the worst things software industry has produced and I'm sad to see how Fowler's introduction to basic patterns mixed with Evan's rather abstract high level ideas keep finding new and new wide-eyed disciples who without think of context treat these two books as some sort of domain specific bible...
Ayende, maybe you can link to some older posts where you discuss possible solutions to the problems you find in the code review.
As a regular reader I know you've also posted about the right way to do it, but even I have a hard time finding the right information in your older blog posts. I think people who only read your code review posts don't even know you've already written about the right way to do it.
There's no need to rewrite the same solution again and again, but some links to your earlier posts that describe 'the right way' would be very helpful.
Bad code is bad code, and pretending it is good or saying nothing to avoid hurt feelings of the people who wrote it won't achieve anything. These projects are showcases of the way to build software and they're hurting all aspiring software developers who read it and think that this is the way applications should be written.
Keep up the good work Ayende.
Keep up your bad code reviews Ayende.
Am I the only one who wants Ayende to do this like a regular series a la Kitchen Nightmares? He can be like Gordon Ramsay.
Ayende, I great respect for what you write and do and I'd love a post on why you dont like repositories and what you think is a better way of doing a typical Raven or NHibernate web site.
I'm glad that you address the issue, and not just sweep it under the rug. I still stand by my criticism, though...
1. No, I don't think that you're evil, but I do see some cyber bullying tendencies. There's a big difference. Evil is evil, whereas bullying is often about reaffirmation needs and frustration. I have been on both sides, a bully and a bullied, both IRL and on the net, so I think I can spot the tendency. It's in the "how", and I think Larz's, Darren's and Fred's comments were spot on, in this regard.
2 No, nothing personal. From your side. But as coders we very much associate ourselves with the code we write, so don't assume that it's not personal for the person on the other side. To quote Meg Ryan, from the romcom "You've got mail": "Nothing personal? Why do people say that? It was personal to me!"
3 There is value in a negative code review. Absolutely! But I don't think it should be exaggerated. Many of us here could fill our blogs with daily negative code reviews. It's quite easy to go into nitpicking mode, especially if you target a single project.
What would be much more useful and a lot less inflammatory is if you'd pick a specific topic or pattern, showed some really bad examples (by all means, with real code) and preferably some suggestions for better solutions in the same context. Derailing a single project and that project in its entirety is a lot less valuable than a topic driven post, and it will continue to result in the kind of reactions you've seen here. Not productive.
Ayende, I -- and no doubt most other developers with any significant industry experience -- agree wholeheartedly with the substance of your criticism of bad code and bad practices. There are a lot of so-called "best practices" being bandied about that are nothing of the sort, but most developers lack the confidence to say so, for fear of being regarded as incompetent by people who have the authority to hire, fire or promote them. The fact that someone (ie yourself) has the guts to stand up and call out "the emperor has no clothes" on this one -- and present us with some solid reasoning why -- just confirms what we were thinking all along, and gives us confidence to eliminate unnecessary layers of abstraction from our projects without feeling guilty about it.
What is at stake, however, is the style of your criticisms here. You don't need a whole week of blog posts to tell us why repositories can be harmful: a single one with a few examples should be more than enough, perhaps with a single follow-up post to show how it should be done right. When you're going over the same ground over and over and over again, it starts to look like you're rubbing people's noses in it no matter how you phrase it, and you just end up getting their backs up and making yourself look like a jerk.
I'm speaking from experience here btw, having made exactly the same mistake myself on occasion...
@Dennis "Do you know of some magical 'Enterprise' code-base that the majority of (who, or what was your defined subject in the second segment of your third sentence?) whoever comprises the parent group of 'many'?"
Was that even a sentence?
People have commented previously on this very blog that they found the project confusing.
The code is by a guy who wrote a book on architecture. If that work represents the the author's philosophy, I question the value of the book. My jack boots make me look very sexy, danke schoen.
The loud formatting in my comment was completely unintentional.
When contributing something to the public, i.e. by publishing an article on a blog or submitting some code in the open, you have to be prepared for some criticism. If you can't deal with that, don't go public with what you have to share. As mentioned above, I believe that the quality of code or the contents of an article can improve by pointing out flaws or imperfections. It's the only way to grow and I think that should be the goal of any author.
That being said, I also agree with what I have read hear, that this is a personal blog, where Ayende publishes what is on his mind. That's his choice, and I do not believe that it is up to us to tell him what he can say or can't say on his blog. That's what freedom of speech is all about, especially on the internet.
For me personally, I follow this blog for some years now, and I always enjoined what was published here. If at some point, I do not like the posts anymore, I am free to leave and never come back again.
I have no problem with the negative code reviews.
My experience with smart people worth learning from, is that any of their time is worth taking. I don't expect them to follow up with a complete series on "how to do it right" or tone down their thoughts to neutral, fluffy criticism.
My best teacher was a guy who probably didn't give a hoot whether I was offended or not. It takes time & effort to try & be a "people-person" as well - skills that I don't expect smart coders to have - nor do I want! Fluffy criticism is less explicit, takes longer to read & write & doesn't have any impact. I'll take whatever Ayende is prepared to give us.
As an example, Fred's suggested "toned down" sentence, specially for sensitive coders, has no character and I nearly fell asleep before finishing it (there you go, that's my negative feedback, complete with character).
"1.You are an evil person and a cyber bully to actually do those sort of things and humiliate people."
That's hyperbole...being right is orthogonal to being rude. But then we do have to consider that at 30 you're not so far removed from your teenage years. Some asshattery is still to be expected.
"2.You have something against the author of the personally, and you set out to avenge them."
I'm pretty sure avenge is not the word you were looking for here (it would seem the law of conservation of irony holds here...in fact, based on many of the comments it seems so does the law of conservation of strawman argumentation).
FWIW I think it's perfectly fine to call out 'guidance architectures' as the over-architected, unnecessary, bloated complexity they are. They just serve to add to the long line of 'enterprise app architecture' more concerned with the technology/process than the problem at hand.
@PandaWood: I agree with you that there is no problem with negative code reviews and personally like to hear the negatives about my own code so I can also learn.
Are you reading this blog for character or the technical usefulness of the content. I am guessing but I think Ayende is not doing this blog for the character but that is just his personality / style showing (not meant to be negative, but fact). I doubt 1 sentence is really going to make you fall asleep.
I also did not suggest "toned down" sentence at all but rather that the relevant information was intact without the additional sentence that added no technical value.
"Fluffy criticism is less explicit, takes longer to read & write & doesn't have any impact." I would suggest that a more objective review (negative or positive) with the facts should be sufficient on its own. I don't think anyone was asking to make it fluffy but rather more objective so these types of debates are not needed.
When you have a non coding architect you usually find big design up front. With big design up front you usually find that 'best practice' is applied before you have fully uncovered the problem you are trying to solve. At least that's my experience too anyway. Reviewing code and highlighting these problems helps our .NET community.
How about providing a full text search so we don't have to rely on the piss poor coding of this blog software to locate specific tags when trying to find the RIGHT way to do something with respect to item #5.
How about that code review big mouth?
Im also very much associated with the code I write. I also gladly welcome any criticism. In fact I'd probably spend many hours talking or listening to someone that was willing to help. And don't worry, you won't hurt my feelings.
the haters can be a vocal minority. keep it up, they've got a great opportunity they're squandering if they aren't fixing their code. plus bad code can solve problems, but is probably accidently functional
Johan, I already wrote about that, see here, for example: http://ayende.com/blog/3955/repository-is-the-new-singleton
To the comments about the style of writing, especially with regards to referring to how I feel about certain things. a) That is how I write. I have very little intention of changing that. b) That is part of what actually makes a post interesting, otherwise, I might as well just put a code listing and that is it. c) A lot of design decisions end up being gut reactions after a while, you know that this is wrong because you react to that, then you break it down to why.
To the comments about people thinking that they are their code. I don't really care. I have little control over what other people do, and people who identify so closely with their code need to pull out and understand that there is actually a difference. If they can't... again, that is not something that I can do much about.
James, Interestingly enough, I did do a short review of the project before. I got an overwhelming amount of criticism about this being an insufficiently detailed review and not a valid way to criticize a project. See: http://ayende.com/blog/152706/application-review-northwind-starter-kit
So I am afraid that no, just a quick note with regards to that is NOT sufficient.
Tom, did you see the right hand side of this blog? On the top, there is a nice search box that does really nice searching on the blog.
@Rafal... This is a general post so I cannot be specific about a problem. Maybe "problem" was not the correct term.... but I think if you read it in context it should be pretty clear. If during a review you think something is coded in a bad way, then suggest a better way. So the"problem" is whatever problem the reviewer has found with the code and what the code is trying to achieve.
I don't expect Ayende to change his style etc. and I know we can search if it is something we are really interested in... but like many have suggested it should be easy to add a link to a better way if one exists (at I higher/conceptual level... I would not expect a code rewrite), and would make these blog posts even more valuable in my opinion.
I have no problem with bad code reviews. But i think you are not right on your point #5. Search your blog and you will find a lot of posts about Repositories and how to use them. Also look at your NH videos from 2007 and later, where the use of Repositories was the only right way to go for you. Then you completely changed your mind and now repositories are an evil thing. This is confusing, especcialy for people who learned things from your blog in the past. On the other hand are explanations about the why a little vague and there are no real examples that show a better way. You wanted to do examples in the past, the last on was Macto, but they never saw the light of day. I think this is one of reasons, why some people here are a little angry about such code reviews and I think no one has a problem when you point out some real bad code (see your last post).
:) "And Ayende said: look and behold, the repository is good. And developers laid their holy infrastructure on this holy pattern. And then Ayende said: look and behold, repository suxx. And there was great angst and bewilderment amongst the developer-folk. And they spoke to Ayende: oh why have you forsaken us and change like customer requirements instead of being holy and static like HttpContext.Current".
The fact that Ayende's views change and improve are one of the reasons I like reading his blog :) If I would ever want to read static, dogmatic and claiming-to-be-right-from-beginning texts, I know few books. Luckily, reality checks in from time to time in software development.
@Bunter +1. If the facts change, or you learn something new, and your opinion DOESN'T change? Then there's something wrong with you.
Yup, +1 for #5. If you don't show how "you" would implement the exact code/requirement under review, its just comes across as bitching and complaining and pointing out faults.
@Ayende:
Thank you for doing these reviews and publishing them. If I ever feel you are being insulting or "mean", I will quit reading them, or perhaps write a review of your reviews and publish that myself.
I applaud that you won't style because some vocal people bitch. Anyone who wants to unsubscribe is able to. Anyone who wants to disagree can publish their opinion just as well. If you want to act on any suggestions you feel are worthwhile, great...
But if I want to read a blog written by committee and combed over to ensure it doesn't offend anyone, I can find that almost anywhere. I prefer substance.
Agree with @Travis, +1 for #5. I appreciate the insight into what is wrong with the code but it only provides half the story and less than half the value. A teacher shows an example of a problem, explains why it is a problem, and then how to correct the problem. Otherwise you're just a critic.
@Bunter very funnny :-) My problem is not that Ayende changed his mind about how things should be done. I just miss the explanation of "why i loved it in the past" and "why i don't love it anymore". That's all :-)
I don't consider myself to be a "hater" or "bitching" about this. I'm not voicing my opinion just because I have it and feel an urge to bash Ayende. I do it because I find Ayende to be a beacon of sanity (the fact that he changed his mind about repositories is just evidence of that), and for me that beacon is dimmed, quite a lot, by these code reviews. I've suggested a different format, focusing on specific bad patterns or practices (with examples from openly available projects), instead of specific projects, and I think everyone can derive even more pleasure, fun and knowledge from that. Your daily dose of WTF can be found elsewhere. It would be sad if Ayende's community leadership was largely based on him taking a piss on other people's code.
"To the comments about people thinking that they are their code. I don't really care. I have little control over what other people do, and people who identify so closely with their code need to pull out and understand that there is actually a difference. If they can't... again, that is not something that I can do much about."
Fair enough. Just don't play the "it's nothing personal" card. That's just a leaky abstraction.
I may be easily offended, but I don't consider taking the empathic route to be the easy or boring way out.
@Oren
O> Tom, did you see the right hand side of this blog? On the top, there is a nice search box that does really nice searching on the blog.
Seriously Oren, you should stop embarrassing yourself like this. For search I put in "needless abstraction" since it's something you like to bash, and per your comments above I was hoping to pull out a few good examples of how you would have handled the situation.
The results are laughable. Here are samples from the first three results, which I'd hope a super-dev like you would make the most relevant.
1) Let us explore all the ways it is broken.
2) Now here are a few problems that I have with this:
3) was completely ridiculous in the level of abstraction
There is nothing to learn from that pathetic search engine, whatever it is you are using.
2)
Hi, I have been reading your code reviews from past month. These are really good comments to understand the current northwind architecture. However, what I feel is negative code reviews should be taken as positive so as to make improvements. Because a creator always thinks he had designed the best solution, but when you review as a third person, you may find some potential problems. I would highly appreciate your efforts if you try to post some templates for architecting the project so that it will clear some doubts about how to architect enterprise applications....
Thanks for your nice reviews. And please keep posting....
I just love those reviews
@Tom
That sounded negative, and almost like a personal attack, better watch out or a bunch of people will accuse you of being a bully.
A good number of you people really need to gain some perspective. A negative review of publicly displayed code is so far from being "cyber bullying" it can't even see it from where it stands. In a day and age where it is a legitimate issue, you are completely cheapening the meaning of the term by trying to apply it here. Grow up, seriously.
To the issue at hand, the most important statement Ayende made is this:
The major reason that I do those negative code reviews is because I keep seeing the same types of mistakes repeated over and over again at customer sites
If anyone wants to post a best practice like that train wreck of a DDD that was put out over the summer, it deserves criticism. Because people tend to forget that .NET programmers love to copy and paste, they love to blindly take what they feel is "best practices" and without thinking put it into their own code bases. Before you know it, there is a big ball of mud that is incredibly expensive to maintain, and it runs like a pig.
This latest project was made to support a book the author is trying to sell as Enterprise solutions, all the more reason to bring up potential problems with the design and implementation.
Ayende is not coming to a developers house, looking over their shoulder and yelling at them about private code, he is commenting on public code that the authors claim is teaching tools.
Are movie critics who bash a bad movie bullies? Are sports writers who point out how badly a losing team played bullies? This is no different.
@ Steve "This latest project was made to support a book the author is trying to sell as Enterprise solutions, all the more reason to bring up potential problems with the design and implementation."
You echo my point as well. This is not an open source project by a guy who is trying real hard and doesn't have experience. The guy wrote a book. About Enterprise practices. All official with MS Press, Dino Esposito etc. It should not be this sloppy and the author should be ready for criticism. This is not bullying, this is not name calling. It is fair game.
@Steve
You must be a new reader of this blog.
@Tom,
Not at all, I've been a reader and poster here for years. What I've learned from your eloquent posts is that you behave a lot worse than anything Ayende has be accused of in this or other review threads. Classic internet tough guy, so pathetic.
Ayende, Negative or positive, the important point in my opinion is that you spend your personal time to write the reviews, for which you deserve a big "Thank you"!
@Steve
Yup, you're definitely a new guy. The thumbprints are all over your posts. You're definitely a Jr. Programmer.
Comment preview