ID:109898
 
Keywords: design
You've had a neat little idea for some code. You've mocked it up and it works quite well for you, you show it to some friends and ... wow! Seems they find it really handy too. "You should make it into a library", they say. But what's involved in this? Today DevTalk will explore how Alathon progressed this into this.

What is it?
The original snippet dealt with taking input from a player who has connected to the BYOND world via telnet. Sounds pretty simple to me, dunno why we'd need a library for this. Well, it turns out there's a lot more to telnet than a mere non-MUD player like myself would think. There's formatting, colouring, spacing, special commands, escaping of characters and so on. My my, much more complicated than I thought ...

Alright, so how 2 library?
Well, firstly the object Alathon made did a load of stuff on New(), like getting ready to grab input from the telnet client. This was fine for his purposes, but it's a bit of an issue for a library. You see, it's quite reasonable to assume someone might do something like:

mob/bridge_troll
var/Input/cunning_riddle = new({"I am agile and strong,
but I cannot win a battle on my own. What am I?"}
)


The problem there? Well, Alathon was expecting you to pass a player straight away. Who could we pass there? No idea, the bridge troll hasn't happened across a hapless hunter yet. Poor library user is a little stuck, and can't very easily re-use the Input object for all people who cross swords with our cunning trollinguist.

The solution? Well, there's many, actually. The one that felt right for this particular library was to move all the fancy logic out of New(). Instead, we move it to getInput(), leaving all the heavy committing code to as late as possible, so the library user can tweak the object to their liking, when they make it AND between calls to getInput(). Success!

But, but, what if the user wants to ...?
Chillax. Deep breaths. You're still the library author, you can decide just how much of the problem you want to handle. The decision of "where to stop" is often a matter of programmer preference. What is important for the library, is it has the kind of behaviour and functions you reckon other people would like. Now whether you make the library really look after the programmer *pat pat* or decide to leave them to it on a matter is up to you, and your preferred style.

An example would be a feature I briefly considered was multiple Input objects working on a user at a time. Alathon rather quickly noted he felt this wasn't worth the complexity (it would have made the user case more flexible, but complicated for the library user), and that he would not be doing it.

As it happens I probably wasn't the library's intended user, and if I felt this was a big deal, I could probably put out my own library, with a different focus to his. There's no real crime in not trying to cater for everyone, each programmer's particular needs are different. I suspect my idea was a little silly, but you can imagine in other libraries, two opposing libraries that do the same thing can both be popular, because they address the same problem but think about different programmer needs. That's cool also, bro.

I'm ready now, right?
Alllllllmost. Well, by almost, I mean "no". A good library isn't worth it's salt without some nice documentation, and maybe a handy fun demo too.

"So I should comment my code?". Kinda. You should write down what process it goes through. Preferably you do this away from the code somewhere, so people never need to look at your code. This isn't because your code is ugly, it's because your code can change. What is important is the processes and features, it's the processes and features people want when they pick up a library. Whether you use copytext to do X is not important to them, so why bother them by making them look at it, nya?

Do I have to document it all ...?
Not really, no. Some of your library will be assisting other things that people use, but "internal". You shouldn't have to worry too much about people mucking with the internals, just as long as you make it clear it's internal.

Now there are plenty of ways you can do this. Name it funky, put a big "WARNING" comment by it, move it into funky named files, and so on. What Alathon did was prefix stuff with __

I quite like this too, actually. It's purely a preference thing though. I also like to push private stuff to the bottom of files, so all the public usable documented stuff is on the top together. As long as it's clear, you're cool.

Fini?
Yes, young code-meister, yes you are. Release and happy librarianing!
The telnet_input library still needs some minor tweaks in order to be what it should be. I went with the method of releasing quickly with a demo, because I needed the library myself in my game.

Now that I've implemented it into my game in several places, and I feel safer that the API is robust, I'll be documenting the public functionality shortly. Even brief descriptions of what a procedure does is better than none.

In addition, when dealing with objects that are stateful, it is often a very good idea to document the states and how they occur. It may not be immediately clear to someone when a state is triggered, how to react when it is, and so on.
Okay I give up!
what is agile strong and can't win the battle on their own? -.-
A rook, in chess. *waits for a chess pro to correct him on the last part of the riddle*
Stephen001 wrote:
A rook, in chess. *waits for a chess pro to correct him on the last part of the riddle*

Ah, very clever!