jump to navigation

writing your own language is bad, m’kay ? September 13, 2006

Posted by Imran Ghory in Software development.
trackback

Joel Spolsky‘s been at the centre of some recent controversy over his VBScript extending language Wasabi — what really shocks me is not that he wrote his own language, but the appalling lack of ability of those attacking his decision to give a coherent argument against it. Forget C – universities obviously need to go back to teaching students rhetoric.

Even some generally intelligent high-profile bloggers such as Jeff Atwood attacked it without giving any justification other than a vastly over-simplistic “writing your own language is bad, m’kay ?”.

Out of the hundreds of people who have commented on it I’ve not seen one person suggesting a reasonable alternative for Joel’s business problem.

So I’d like to throw out the question what would you do in the following situation:

You have a product which is deployed to client web-servers and is written in VBscript, your market research has indicated that having your product work under more web environments (i.e. non-VBscript ones) would bring in significantly more sales. Having looked into it you find that getting the clients to install a new run-time environment or language is unviable – too many are unwilling to do this. So you have to use something that’s already installed almost everywhere (or at least everywhere you can’t deploy VBScript) – a quick look at Netcraft will tell you that the answers PHP.

So now you know you need to port your app to PHP, how would you do it ?

You could do it by hand and then forever after have two codebases you’ld have to keep in sync. Anyone who’s ever tried to do that before will know down that path lies years of pain and maintenance nightmares.

You could make a framework in both languages which is data driven, trying to move as much of your application code as possible into the data. But this is essentially the same as coming up with a new language and writing an interpreter for it in both PHP and VBscript.

You could write a program which turned your VBScript into PHP. This seems essentially the route Joel took (adding some extra functionallity while he was at it).

Anyone have any other suggestions for how you would solve this problem ?

Because frankly Joel’s solution is the best programming solution to his business problem that I can think of.

Advertisement

Comments»

1. No Google Stalkers, thanks - September 14, 2006

People are heckling him for writing a blog post about how he told his friend to use j2ee instead of rails because j2ee has more people using it. Then, his next post was about his own internal language that only four people know. The hubub is about how he gives wildly varying advice.

“Forget C – universities obviously need to go back to teaching students rhetoric.”

Maybe you need to learn some reading comprehension.

“Even some generally intelligent high-profile bloggers such as Jeff Atwood attacked it without giving any justification other than a vastly over-simplistic “writing your own language is bad, m’kay ?”.”

I can’t see that text on Jeff’s post. Libel is bad, m’kay?

“You have a product which is deployed to client web-servers and is written in VBscript, your market research has indicated that having your product work under more web environments (i.e. non-VBscript ones) would bring in significantly more sales.”

You should have thought of that before being locked into proprietary technologies.

“Anyone have any other suggestions for how you would solve this problem ?”

One solution is to license servers like Google does it’s search appliances. Failing that, do what Joel did; but then write a blog post about how stupid it is to lock into unportable proprietary technologies instead of a post about how people shouldn’t use open source and portable Ruby based on not enough people using it and its speed.

2. brainfsck » Derailed debate - September 14, 2006

[…] I’ve been actively following what Haacked calls The Joel Cycle. It looks like tickletux is one of the few people that actually took the time to digest what Joel said, instead of just crying out “OMG he’s bashing Rails!”. […]

3. Daniel Slaney - September 14, 2006

Good post and you’re right. The problem was he offended the Ruby and RoR fanboys and now faces their childish wrath. Not that Ruby or RoR are bad, they’re pretty cool pieces of tech.

4. RBI - September 14, 2006

You’re exactly right. Joel did exactly the right thing with the requirements he was facing. Had his friend come to him (regarding the article that started all of this) with the same problems that Joel was facing (5 year old codebase and need to port to multiple platforms), Joel would have given the exact same advice.

5. Simen - September 14, 2006

RBI: how do you know? Do you know Joel personally?

The controversy was about him saying Ruby/Rails is not the right solution because it doesn’t have the massive support that other solutions have, but in the same post he says he has chosen to use a home-grown language with literally no support outside his company.

Now, Ruby/RoR might be a bad solution for lots of other reasons, and that’s okay, but as it stands, the argument is just a bunch of hypocricy.

For the record, I use Ruby, but not Rails.

6. Mathieu Fenniak - September 14, 2006

My recommendation would have been a one-time port to a language like PHP, aided by the use of automated tools as necessary. This would leave you with one code base, written in one language, that runs on multiple platforms quite nicely. You wouldn’t need to maintain your own language compiler until the end of time. Even better, in fact — other people are hacking away at PHP, giving you new language features and libraries every once in a while with zero effort.

7. RBI - September 14, 2006

Mathieu: Your recommendation doesn’t fit his requirements. He wanted to require no installation on a default Windows server (they all support asp out of the box).

Simen: His post had two parts: 1) He explained to his friend that he didn’t think RoR was a good solution for a person looking for a safe bet at a company where they might get fired if things didn’t work out and 2) he explained why he personally didn’t want to use Ruby.

His language is a superset of VBScript. It takes VBScript and spits out PHP. It has some language extensions on top of VBScript as well.

It fits his requirements perfectly and is a technique that has been recommended by everyone from MacDonnel (Code Complete) to the Pragmatic Programmers.

You guys really have to read the articles before you respond to them.

8. AN - September 14, 2006

Simen,

Since when is advocating two different approaches for two different situations hypocrisy? Oh wait, it’s not.

The language is still apparently a close descendant of VB, so I doubt it would be that hard for newcomers to learn.

Using a homebrew language that compiles down to a pre-existing, proven platform completely eliminates most of the reasons for writing a new platform. Deployment issues, scalability — these things aren’t an issue if you piggyback on top of an existing platform.

By contrast, if you want to deploy enterprise websites built with rails, the SBCL lisp implementation, or the GHC haskell compiler, you’re going to have to test the platform carefully, because none of them have a sufficiently large base of proven enterprise deployments yet.

9. Simen - September 14, 2006

The homebrew language doesn’t have any sufficiently large base of proven enterprise deployments yet, even if the platform it is built on has. There could be any kind of bug in the compiler, and then you’re screwed no matter what platform you compile to. That’s like saying that any compiler that compiles to assembly has tons of proven deployments, since almost all [compiled] languages ultimately compile down to assembly.

10. dennis w. forbes - September 14, 2006

Boy, Joel sure got some link love from this. Lesson learned, I’m sure he’ll say all sorts of controversial things over the coming while.

“You could write a program which turned your VBScript into PHP”

If Joel said that they wrote a VBScript -> PHP converter (we already knew they had), and converted their code and then continued with the full abilities and libraries and functionality of PHP, then there would be no debate. It’s a bit disingenuous presenting it in such a way.

Instead he’s saying that they made a language superior to both, which “compiles” to multiple target languages, and on going forward this is their modus operendi. That is rather odd, and it is the part that people paid attention to and found hard to believe. Not only does it seem dubious that the tiny team of relatively short-on-experience developers at FogCreek really have the ability to out-language the industry, but it sounds clunky and sort of ridiculous. Not to mention that in reality I’m sure it’s -far- more trivial than many have come to believe (e.g. bullks of code in both languages with some template sections where some macro code is, err, “compiled” into them).

11. bonko - September 14, 2006

Seems to me that by declaring Wasabi Joel created this silliness. From what I understand, it is a dialect of VBScript with annotations that make conversion to PHP possible.
The tool for doing this could be called a ‘compiler’, but seems more accurate to call it a translator. The line between the two is fuzzy, but compilers are generally assumed to extract the meaning of the input into an internal structure, then use this semantic information to generate bytecode (or in some cases, a lower level language).
Code generation makes sense. Code generation to a similar dynamic platform based on institutionalized annotations is perfectly reasonable.
Creating a new language and a compiler that targets two dynamic languages as output seems unreasonable.
I have no real idea what wasabi is or how it works, but it seems to me that the terms used in describing it can indicate something reasonable or something rather unreasonable, depending on how you interpret them.

12. Orion Edwards - September 14, 2006

Sure, in theory he wants an out-of-the-box windows server solution, but also wants PHP, so writing a cross compiler would be the way to go, yes?

WRONG ( …in my quietly humble opinion of course… )

The client needs to install fogbugz. They at some point run some installer or deply some package, regardless of what OS they have. PHP is not some magical thing that you either have or you don’t (like OSX for example). You can (quite easily I might add) bundle PHP into your windows installation scripts/MSI/exe/whatever, so the client wouldn’t even know. Heck, you can change IIS so that .asp files under a certain directory are actually loaded and run by PHP if you really want.

I stand by my original comment (somewhere on the JoS boards).
Joel’s motto is ‘hire rockstar developers and keep them happy’. Most ‘rockstar’ developers will get sick of writing trivial web apps in vbscript. I bet Joel had one of these, who wanted to do compilers and systems programming, (don’t they all these days?) but he couldn’t afford to lose the guy, so he let the guy go mental and create Wasabi. It all makes sense no?

13. Ravenlock - September 14, 2006

Dennis, I think Bonko hits very close to the meat of the matter — it’s not very likely that the Fog Creek team could out-language the whole industry, but it’s very likely that *they know exactly what a language needs to be suitable for this one application*. I wish I could somehow emphasize that bit even more. This is a *domain-specific language* we are talking about, although instead of being interpreted or compiled to byte- or native code, it’s being used to generate code in other languages. It’s unusual but certainly not unheard-of.

14. tickletux - September 14, 2006

Orion Edwards: I don’t know if you’ve worked in the corporate software development world, but in many companies a software package which behaved in such a way would be unacceptable. There are many reason for this ranging from security, to legal, to support issues,etc. Joel in particular mentions that his market research indicates a competitor’s product which is written in Java is rejected by many companies because a JVM is not part of their web-server enviroment. You have to remember that all of his clients have software developers – they’re not lacking the skills required to install a JVM, etc. rather they choose not to do so for business reasons.

15. mike bayer - September 14, 2006

you shouldnt be shocked at all. Joel attacked Ruby, plain and simple. and these days thats a big gauntlet to throw down.

the subsequent ad-hominem musings of DHH (not just one but two blog posts for this one) result in the logically fallacious “stay-on-message”-style talking points of “inventing a language is bad” (its not)/”Joel contradicted himself” (he didnt) to flourish. With a bonus meme of “being slow and bloated doesnt really matter” thrown in for good measure.

The first two of which don’t address Joel’s actual point, and all three of which do nothing towards helping to fix Ruby’s slowness/bloatedness/non-concurrentness/non-unicodeness anytime soon.

16. AN - September 15, 2006

>> The homebrew language doesn’t have any sufficiently large base of proven enterprise deployments yet, even if the platform it is built on has. There could be any kind of bug in the compiler, and then you’re screwed no matter what platform you compile to. That’s like saying that any compiler that compiles to assembly has tons of proven deployments, since almost all [compiled] languages ultimately compile down to assembly.

How is the possibility of a bug in a compiler that you build yourself any different than a bug in a web page or business logic class or database access layer you build yourself? Compilers aren’t magic fairy dust that are somehow categorically different from any other code — if it’s your code, you test it, track down the bugs, and fix them. It deploys to a platform that has been proven to be scalable, so your only scalability concern is that you wrote poorly optimized code, which you can test for and fix.

By contrast, suppose that there is a chunk of the Ruby interpreter that scales poorly. Would you want to fix it? I wouldn’t. It would take forever to learn enough about the code base to do anything useful with it.

It’s when you depend on other people’s code that you’re not competent to fix that you need a proven toolchain.

Normally, it’s easier and more efficient to use someone else’s prebuilt, proven toolchain than to build your own. But if there’s a gap in your toolchain that needs to be filled — like, say, a VBScript to PHP compiler — it may be a heck of a lot more efficient to just fill the gap with an internal tool than to just give up and start over with different tools.

17. Simen - September 15, 2006

“How is the possibility of a bug in a compiler that you build yourself any different than a bug in a web page or business logic class or database access layer you build yourself? Compilers aren’t magic fairy dust that are somehow categorically different from any other code — if it’s your code, you test it, track down the bugs, and fix them. It deploys to a platform that has been proven to be scalable, so your only scalability concern is that you wrote poorly optimized code, which you can test for and fix.”

It’s not different, it’s just that a commercial or open source compiler/interpreter is going to have lots of other people to fix bugs, leaving you to focus on your business problem.

I’m not saying that writing your own language is always a bad idea. I’m saying that arguing about how a language needs community/commercial/whatever support, and then you go on about how you built your own language is stupid. It sounds like a contradiction to me, and it certainly distracts from the main point, which was that Ruby was the wrong choice, which may very well be true.

18. R - September 15, 2006

And what happens when a client doesn’t have PHP installed on a server that they have? There are plenty of alternatives to Joel’s situation, because I bet you $10 the number of people who would refuse to install a runtime would cost him less in lost sales than the time taken to write and support a new language.

He could have moved to Java, and then he would only be setting up Tomcat (whatever it is called now) or somesuch on the machine.

He could have gone PHP on Windows.

He could have gone ASP on *nix.

He could have followed his own hype about .Net and gone all .Net by using Mono on *nix.

He had lots of choices, as do hit customers. The customer doesn’t care that you went out of your way to make sure it runs with something that *may* already be installed on your server, the customer cares that the product they want to buy works and does what it says on the tin – without hidden extras.

In the past decade of software development, with some *very* large corporate customers only 2 have ever refused to install extra software in support of a product, and those that have quibbled are those that didn’t know in advance what technology was used with the product.

19. Richard - September 15, 2006

What Joel was asked: “What should I do my _brand new_ development in”

What Joel replied: “Some well established language”

What Joel did himself: Several years ago, took his own advice and used an established, well known and tested language – VBScript.

What happened since then: ASP, ASP.NET, PHP became the _new_ established, well known and tested languages, and portability to other OSs and easier customer installation and support became issues.

What he did: Leveraged the existing codebase with many many years of development and generated a compiler to convert to the new languages, while improving installation issues.

I’m sorry, but what is so wrong with that?

And remember, any time you force your customer to install some new server/library/bla for your code – be it php, ruby, mono, etc etc. – you are also forcing them to handle maintainance, upgrading, security patching, etc. of that code.

As the CIO of a company, would you rather you staff looked after one server stack that runs all the web apps, or would you like to maintain PHP for the bug tracker, Ruby for calendaring app, ASP for webmail, ASP.NET for the CMS etc? (Not to mention mysql & postgres & oracle &…)

20. Mike Dimmick - September 15, 2006

Yup. Joel _started_ with a VBScript-to-PHP converter. At this point you have FogBugz written in VBScript and ASP but able to run on ASP on Windows and PHP on Unix.

Then they add some feature which is highly verbose and repetitive to implement directly in VBScript. To reduce the verbosity and remove the possibility of accidentally getting one of the repetitions wrong, they use a code-generator which generates VBScript. They already have a VBScript parser, so the new language features to support the code generation get glued into their existing translator – and this has the benefit that your domain-specific language can be inline with the rest of your code, and becomes first-level language features.

It wouldn’t be too surprising to have the intermediate representation actually _be_ VBScript: the front-end parser then parses ‘Wasabi’ and generates the VBScript/ASP pages (pass 1), then the old tool generates the PHP version of the ASP pages (pass 2). Your testing can then be split into two phases: ensuring that pass 1 generated the correct ASP/VBScript, and ensuring that pass 2 generated the correct PHP for that ASP. For most features that don’t use any new Wasabi language features, pass 1 of the translator presumably just copies the input to the output.

As others have said, the Ruby thing is a bit of a red herring as he was advising his friend on what to use for a clean-slate system. FogBugz had path-dependence – a lot of investment in existing VBScript/ASP code that Joel didn’t want to discard.

Lilly - September 27, 2011

A good many vlaualbes you\’ve given me.

rohujo - October 1, 2011
21. Leonardo Herrera - September 15, 2006

To R (#18): You are arguing about things you don’t know about. Any of the “advices” you are giving (using PHP on Windows, ASP on unix, Mono and .NET, and Tomcat for God’s sake) would have cost them customers. FogCreek is a small company; I bet they did their homework, and found that having a simple installer was a sound business decision.

But hey, bashing Joel is fun, right?

22. R - September 15, 2006

Leonardo, okay so my knowledge of the Java stack is a little out of date but I think you are missing my point. My point wasn’t that any of those suggestions were particularly good ones, but rather that he had choices, and to choose the one he did was probably wrong given that the target audience is developers, not *typical* IS departments of Fortune 500 companies.

I’m not bashing Joel at all, I’ve got a lot of respect for him even though in this particular case it was all a little ‘do what I say, not what I do’ but *everyone* is entitled to their opinion.

I seem to have been missing *your* attempt at being constructive …

But hey, bashing commenters is fun, right?

23. Richard - September 15, 2006

R[22]: Sorry my example was too Enterprise-y for you. So to go to the other end of the scale.

You are a small ISV. You used to just keep the bugs in a to-do list, but you are just getting big enough that some issue-tracking software is needed to keep on top of things. You could just use bugzilla but time is money, so the saved time from something nice and integrated like Fogbugz or a similar competitor is worth the money.

Now do you want to:
A) Install some whole new stack just to evaluate it, and then – if you do buy – spend a couple of hours a month extra to ensure that you keep this new stack patched and up-to-date?
B) Evaluate – and perhaps buy – the system that “just works” on whatever stack you already have, and use those extra couple of hours to do things that actually make you money.

Worse still, if you are someone who thinks nothing of (A) then you are probably also someone who will just use bugzilla because it’s free and you can just tweak it to more closely match what you want.

So at both ends of the scale, “it just works” is a major selling point. Time is money. If you take less of my time you can have more of my money, and this is true whether you are a CIO worrying about IT budgets, or a startup worrying about eating.

24. Jacob - September 16, 2006

R (post #18): “I bet you $10 the number of people who would refuse to install a runtime would cost him less in lost sales than the time taken to write and support a new language.”

Did you read what Joel wrote about this? IIRC, he said it took one developer about 2 months. If you have any idea how much FogBugs costs, it shouldn’t be too hard to do the math and get a rough idea of how many additional they would have to sell to make this investment pay off. Here’s a hint: it’s not very many. In contrast, every single one of the alternatives you offered would probably result in hundreds of thousands of dollars in lost revenue (and that’s a conservative estimate).

Also, writing and maintaining a DSL is not that big a deal because the scope is usually very limited.

25. R - September 18, 2006

Richard[23]: How would I evaluate it? I’d try the online demo which would have *very* limited impact on my time because I have to do absolutely zero to get this to work. I am totally behind the It Just Works thing (it is why I love my Mac), but there are other ways that they could have just made it work – not that I am -that- bothered that they wrote their own language, it is their time and effort not mine, how does it affect me?

What I did object to was the hypocrisy of telling people to use mainstream tools and then not practising what you preach.

Jacob[24] If 2 months is the total time required to build the fully functioning bug free, no maintenance product that maybe I am wrong, I am quite open to the idea of being wrong – it has happened before. Somehow though I suspect that the 2 months was a flip comment that doesn’t take into account bitrot.

I agree about DSLs, I’ve used one or two before, but I am not sure I would give Wasabi that label – it isn’t domain specific it is a dev tool for cross-compilation.

26. R - September 18, 2006

Not that there is an online demo of FogBugz where I can put in some bugs and push it through the workflow. Maybe FogBugz\\\\\\\\’s bugs could have been put into an online bug-tracker – I did notice that a lot of the free bug trackers all have online demo installations you can try.

27. Brad Bellomo - September 18, 2006

I agree, there is much criticism on developing a new language that is unwarranted. 15 years ago, people were writing their own languages just for the heck of it, also unwarranted. There is nothing really wrong with doing this.

In Joel’s case, I would not have done the same. His product is small (probably

28. Jacob - September 18, 2006

R (post #25) “Somehow though I suspect that the 2 months was a flip comment that doesn’t take into account bitrot.”

Even if they had to invest the equivalent of six full time months a year into maintenance (which I highly doubt it’s even a fraction of that), it would probably still make financial sense for them. If you take into consideration what FogCreek probably spends on payroll without support for both ASP and PHP, they wouldn’t have had to increase sales by that much to turn a profit on creating and maintaining Wasabi.

But now we’re taking wild guesses at FogCreek’s revenue figures, the percentage of sales that are attributable to having installs for both platforms, and the amount of maintenance they have to put in. So it seems like all this hand waving from a bunch of programmers who probably couldn’t run their own business, let alone know the first thing about Joel’s, is just plain stupidity. Say what you want about Joel, but he knows how to run a business. I’m sure he ran the numbers on building AND maintaining Wasabi to see if it made sense. If it didn’t, you can be pretty sure he would have dropped it like a hot rock.

And how is Wasabi not domain-specific? While they didn’t invent a whole new language syntax from the ground up, it sounds like they extended an existing language to provide both syntax and functionality specifically (and pretty much exclusively) for their problem domain.

29. Richard - September 19, 2006

R[25]: “What I did object to was the hypocrisy of telling people to use mainstream tools and then not practising what you preach.”

I refer you back to my first comment – [19]. What I said then:

“What Joel was asked: “What should I do my _brand new_ development in”

What Joel replied: “Some well established language”

What Joel did himself: Several years ago, took his own advice and used an established, well known and tested language – VBScript.”

What Wasabi appears to be about is leveraging his investment in vbscript as the web programming landscape changed to other languages. That is clearly not the same as starting a brand-new development.

In fact, to make this even more clear, the original question included the line: “The project is starting from scratch and so there is no legacy code involved.”

Had the questioner instead stated “I have 5 years of vbscript code developed that I would like to leverage if possible,” then we Joel’s answer may very well have been different.

Answering two different questions (new development -v- leveraging existing code) in two different ways is not hypocrisy, it is a sensible design decision.

30. Josh - September 19, 2006

I understand writing your own code generator to leverage existing code. The thing I don’t get is why they’re still using it. They should have converted the code base to PHP and left vbscript in the dust. People have been talking about forcing customers to install a whole new stack? ITS PHP! They’re customers almost certainly have PHP installed and if they don’t you can bundle it with the install/update. Seems to me continuing to use wasabi/vbscript avoids some short term pain, but is going to create a royal pain in the ass in the long term.

31. Richard - September 19, 2006

Josh[30]: If your servers are currently running ASP.NET then PHP is a new install. While cheap shared-hosting servers do almost all have PHP, the same is probably not true in the corporate “bought a server from Dell and chucked in a rack” market.

Like I’ve said before (c.f. 19, 23), it is not just installing PHP. That is trivial. It is maintaining PHP, making sure you are up-to-date, have all your security patches, etc etc. that kills you.

32. Jacob - September 19, 2006

Richard: “People have been talking about forcing customers to install a whole new stack? ITS PHP! They’re customers almost certainly have PHP installed and if they don’t you can bundle it with the install/update.”

Why is such a simple concept as “Customers * Price = Revenue” so difficult for some people to grasp? I don’t know where you work, but at most of the companies where I’ve done consulting which use IIS and ASP/ASP.NET, they most definitely do NOT “almost certainly have PHP installed.” And I can say with a good deal of certainty that most of them would not even try FogBugs if PHP was required to run it (bundled or not) as long as there was another bug tracking solution that did not require PHP. In case you’re still not following, that translates to a whole lot of lost revenue.

It’s almost comical to see people trying to argue against Joel’s decision using stupidly obvious arguments that he certainly already considered. It’s obvious to anyone who thinks about it that any single technology stack you propose as an alternative Joel’s solution absolutely WILL cause you to loose a certain percentage of customers. Technological considerations are completely irrelevant to the discussion. The only question is what that percentage is, and whether those additional sales are enough to pay for the extra development and maintenance time. Joel obviously believes it does, and he’s in a much better position to know than you are. If you actually took a second to do the math, you would see that he probably wouldn’t have to increase sales by much for ASP and PHP support pay off – easily as little as 3-5%, which is next to nothing.

33. Over it! - November 4, 2006

You’re all giving far to much energy to this $h!t. Time will tell if Fogcreek took the right approach.

IMHO I think a bug tracker does not require a *new* language or compiler or translator or whatever you damn well want to call it – I mean – it’s a bug tracker for Christ’s sake. Jeez.

34. Hey Language Snobs: Don’t Pinch Pennies » What’s In Peter’s Head - June 4, 2008

[…] simple comment set off a crazed irrational firestorm of criticism, cataloged here. People even thought it was a joke! These people were pinching pennies […]

35. nessBeinept - October 21, 2008
36. ray ban vagabond 01 - November 24, 2015

Jersey is very good, and give them to buy not seen the effect of wear, and why 10 0 printed word interface missing it? I have seen several such evaluation is not changed.
ray ban vagabond 01 http://lapvang.com/CloudCastle.aspx?cjBiMDMwMjM0NTU2YTdhMjc.html

37. NLBiztrord - June 16, 2018

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: