<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
    <channel>
        <title>DevTalk's site</title>
        <link>http://www.byond.com/members/DevTalk</link>
        <description></description>
        <lastBuildDate>Fri, 10 Feb 2012 18:58:18 +0000</lastBuildDate>
        <language>en-us</language>
    
                <item>
            <title>From idea to library</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=109898</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=109898</guid>
            <pubDate>Tue, 22 Feb 2011 22:24:05 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=109898#comments</comments>
            
            <description>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. &quot;You should make it into a library&quot;, they say. But what's involved in this? Today DevTalk will explore how Alathon progressed &lt;a href=&quot;http://www.byond.com/members/Alathon?command=view_post&amp;post=109303&quot;&gt;this&lt;/a&gt; into &lt;a href=&quot;http://www.byond.com/developer/Alathon/telnet_input&quot;&gt;this&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;What is it?&lt;/b&gt;&lt;br&gt;
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 ...&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Alright, so how 2 library?&lt;/b&gt;&lt;br&gt;
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:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
mob/bridge_troll&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/Input/cunning_riddle = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;dmstring&quot;&gt;{&amp;quot;I am agile and strong,&lt;br&gt;but I cannot win a battle on my own. What am I?&amp;quot;}&lt;/span&gt;)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
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.&lt;br&gt;
&lt;br&gt;
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!&lt;br&gt;
&lt;br&gt;
&lt;b&gt;But, but, what if the user wants to ...?&lt;/b&gt;&lt;br&gt;
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 &quot;where to stop&quot; 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.&lt;br&gt;
&lt;br&gt;
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.&lt;br&gt;
&lt;br&gt;
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.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;I'm ready now, right?&lt;/b&gt;&lt;br&gt;
Alllllllmost. Well, by almost, I mean &quot;no&quot;. A good library isn't worth it's salt without some nice documentation, and maybe a handy fun demo too.&lt;br&gt;
&lt;br&gt;
&quot;So I should comment my code?&quot;. 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?&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Do I have to document it all ...?&lt;/b&gt;&lt;br&gt;
Not really, no. Some of your library will be assisting other things that people use, but &quot;internal&quot;. 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.&lt;br&gt;
&lt;br&gt;
Now there are plenty of ways you can do this. Name it funky, put a big &quot;WARNING&quot; comment by it, move it into funky named files, and so on. What Alathon did was prefix stuff with __&lt;br&gt;
&lt;br&gt;
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.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Fini?&lt;/b&gt;&lt;br&gt;
Yes, young code-meister, yes you are. Release and happy librarianing!</description>
        </item>
                <item>
            <title>Design in BYOND: Interfaces?</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=109835</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=109835</guid>
            <pubDate>Mon, 21 Feb 2011 11:46:21 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=109835#comments</comments>
            
            <description>Disclaimer: The code in this DevTalk is untested and was written as I wrote the article, so it may contain bugs. Feel free to mention any you find in the comments, and I'll correct the code.&lt;br&gt;
&lt;br&gt;
Interfaces are an OOP concept that BYOND has no notion of. If you're unaware of what an interface is, there are plenty of Google-able resources on the subject (Or for the lazy, &lt;a href=&quot;http://download.oracle.com/javase/tutorial/java/concepts/interface.html&quot;&gt;see here&lt;/a&gt;).&lt;br&gt;
&lt;br&gt;
The problem that interfaces are often there to solve, is this one:&lt;br&gt;
&lt;br&gt;
What if you have a number of classes which carry no resemblance to eachother, but a different class wants to use any one of them in the same fashion.&lt;br&gt;
&lt;br&gt;
For a specific example, in my game I have a /menu object and a /form object. A menu can link to another /menu, but it can also link to a /form. And yet, the /form has absolutely nothing to do with a /menu, and can exist just fine on its own. The /form is simply a series of questions the user is asked, where-as a menu is a static object that allows the user to walk through the menu, its children, and so on.&lt;br&gt;
&lt;br&gt;
So how do you solve a dilemma like this? As with most things within programming, there are numerous methods to achieve the above. Some of which are pretty sketchy and not very robust, some of which are.&lt;br&gt;
&lt;br&gt;
Lets simplify things and say we have the following scenario:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
apple&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/describe()&lt;br&gt;        world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&amp;quot;Apples are yummy!&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;car&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/describe()&lt;br&gt;        world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&amp;quot;Car goes wrooom!&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;describe_item&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/datum/D&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/setItem(datum/D)&lt;br&gt;        src.D = D&lt;br&gt;&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/Go()&lt;br&gt;        D.describe() &lt;span class=&quot;dmcomment&quot;&gt;// Uh oh! We can't do this&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Ignore for the sake of this example that the above could use a variable to describe the object - The example is kept simple in order to be easier to grasp.&lt;br&gt;
&lt;br&gt;
The above obviously isn't possible, as /datum has no describe() procedure. And if we don't want /apple and /car to descend from the same parent, we've got an issue we need to solve.&lt;br&gt;
&lt;br&gt;
The smart reader might go, 'You can use istype() for this!', and they'd be right. But lets see how that looks, for a moment:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
apple&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/describe()&lt;br&gt;        world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&amp;quot;Apples are yummy!&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;car&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/describe()&lt;br&gt;        world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&amp;quot;Car goes wrooom!&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;describe_item&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/datum/D&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/setItem(datum/D)&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(istype(D, /apple) || istype(D, /car))&lt;br&gt;            src.D = D&lt;br&gt;&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/Go()&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(istype(D, /apple))&lt;br&gt;            &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/apple/A = D&lt;br&gt;            A.describe()&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(istype(D, /car))&lt;br&gt;            &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/car/C = D&lt;br&gt;            C.describe()
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
Woohoo! Home safe! Except.. the above really looks like we've duplicated a lot of code. And what if we want to add another object? More istype()'s. If we want to remove an object, we have to adjust both procedures too.&lt;br&gt;
&lt;br&gt;
The smart reader might now go, 'You can use the : operator, and write a separate procedure to check the type of the datum!', and they'd be correct again. And this IS one solution. However, it still requires you to maintain the procedure doing the type-checking, and still feels pretty ugly to me.&lt;br&gt;
&lt;br&gt;
I have a different suggestion: Emulate the spirit of interfaces, and joy will be had by all.&lt;br&gt;
&lt;br&gt;
DM has a call()() procedure, which allows you to call a proc, or a proc belonging to an object. We could wrap this functionality in an object and maintain a list of legal functions to call. This way we get around having to check types, instead we can check whether the function we want exists with hascall() - And this can be done dynamically and all nice.&lt;br&gt;
&lt;br&gt;
For example:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
datum/&lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/publicFunctions()&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/list()&lt;br&gt;&lt;br&gt;callWrapper&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;&lt;br&gt;        datum/__obj&lt;br&gt;        list/__func=&lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()&lt;br&gt;&lt;br&gt;    New(datum/__obj, list/__func)&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!istype(__obj)) &lt;span class=&quot;dmkeyword&quot;&gt;del&lt;/span&gt; src&lt;br&gt;&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!istype(__func)) &lt;br&gt;            __func = __obj.publicFunctions()&lt;br&gt;        &lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;for&lt;/span&gt;(&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/a &lt;span class=&quot;dmkeyword&quot;&gt;in&lt;/span&gt; __func)&lt;br&gt;            &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!hascall(__obj, a))&lt;br&gt;                __func -= a&lt;br&gt; &lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!length(__func)) &lt;span class=&quot;dmkeyword&quot;&gt;del&lt;/span&gt; src &lt;span class=&quot;dmcomment&quot;&gt;// No functions to call&lt;/span&gt;&lt;br&gt;   &lt;br&gt;        src.__obj = __obj&lt;br&gt;     &lt;br&gt;        src.__func = __func&lt;br&gt;&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;&lt;br&gt;        Call(f)&lt;br&gt;            &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(!f || !(f &lt;span class=&quot;dmkeyword&quot;&gt;in&lt;/span&gt; __func)) &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt;&lt;br&gt;            &lt;br&gt;            &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(length(args) &amp;gt; 1) &lt;br&gt;                &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/list/L=&lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()&lt;br&gt;                L = args.Copy(2)&lt;br&gt;                call(__obj, f)(arglist(L))&lt;br&gt;            &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt;&lt;br&gt;                call(__obj, f)()
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
So that was a lot of code. What does it do?&lt;br&gt;
&lt;br&gt;
The idea behind the callWrapper object is more or less what it sounds like. It wraps calls in an object. You supply it with an object, and optionally a list of functions that can be called, and it does the rest. In order to actually call that function, you use callWrapper.Call(function_name).&lt;br&gt;
&lt;br&gt;
The callWrapper object will make sure that any function specified in the __func list in New() actually can be called, and that if there are no 'legal' functions left, or you didn't supply a datum as __obj, it'll delete itself.&lt;br&gt;
&lt;br&gt;
Lets try to apply the callWrapper object to our initial case:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
apple&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/describe()&lt;br&gt;        world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&amp;quot;Apples are yummy!&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;car&lt;br&gt;    publicFunctions()&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/list(&lt;span class=&quot;dmstring&quot;&gt;&amp;quot;describe&amp;quot;&lt;/span&gt;)&lt;br&gt;&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/describe()&lt;br&gt;        world &amp;lt;&amp;lt; &lt;span class=&quot;dmstring&quot;&gt;&amp;quot;Car goes wrooom!&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;describe_item&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/callWrapper/W&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/setItem(callWrapper/W)&lt;br&gt;        src.W = W&lt;br&gt;&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/Go()&lt;br&gt;        W.Call(&lt;span class=&quot;dmstring&quot;&gt;&amp;quot;describe&amp;quot;&lt;/span&gt;)&lt;br&gt;&lt;br&gt;&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/apple/A = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()&lt;br&gt;&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/car/C = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()&lt;br&gt;&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/describe_item/describe_apple = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()&lt;br&gt;&lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/describe_item/describe_car = &lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;()&lt;br&gt;&lt;br&gt;describe_apple.setItem(&lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/callWrapper(A,list(&lt;span class=&quot;dmstring&quot;&gt;&amp;quot;describe&amp;quot;&lt;/span&gt;))&lt;br&gt;describe_car.setItem(&lt;span class=&quot;dmkeyword&quot;&gt;new&lt;/span&gt;/callWrapper(C))
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
The good thing about this, is that if you wanted to be able to describe trees, or a menu, or some internal object, or something else totally unrelated to all the rest, all you'd have to do was give it a describe() procedure. The above also shows the two different ways to deal with the callWrapper object - By overwriting publicFunctions(), or passing any functions that you want to call as a list to its constructor.&lt;br&gt;
&lt;br&gt;
This is in fact closer to automatically inherited interfaces, which &lt;a href=&quot;http://golang.org/&quot;&gt;Google Go&lt;/a&gt; implements. And automatically inherited interfaces are awesome, for a variety of different reasons.&lt;br&gt;
&lt;br&gt;
This callWrapper is also great any time you want to export some functionality in a library, and you want the API to be very simple. Lets say you have an object and you want to let the user define how it is displayed in a chat panel. You might in that objects constructor give the user the ability to pass it a callWrapper, and then in the descriptive function for the object, you'd use the callWrapper if it existed. That might look like this:&lt;br&gt;
&lt;br&gt;
&lt;div class=&quot;dmcode&quot;&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;dmcode&quot;&gt;
menu&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;var&lt;/span&gt;/name = &lt;span class=&quot;dmstring&quot;&gt;&amp;quot;Some Menu&amp;quot;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/describeMenu()&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;if&lt;/span&gt;(__wrapper) &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt; __wrapper.Call(&lt;span class=&quot;dmstring&quot;&gt;&amp;quot;describeMenu&amp;quot;&lt;/span&gt;)&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt; __defaultDescribe()&lt;br&gt;&lt;br&gt;    &lt;span class=&quot;dmkeyword&quot;&gt;proc&lt;/span&gt;/__defaultDescribe()&lt;br&gt;        &lt;span class=&quot;dmkeyword&quot;&gt;return&lt;/span&gt; src.name
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
I may release a small library with this functionality (and some extra functionality), if I can convince myself its not just a small snippet but actually a library ;)</description>
        </item>
                <item>
            <title>Branches, Tags, and a nice Trunk.</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=107370</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=107370</guid>
            <pubDate>Fri, 21 Jan 2011 18:27:49 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=107370#comments</comments>
            
            <description>At one point or another, you'll have likely heard of this voodoo called SVN. SVN is something that allows group collaboration to happen in a structured atmosphere, creating a union between different versions of code, and an overall easy way for developers to work on different parts of a project, and gracefully merge them together without having to go through the trouble of having one guy sit alone in his home office for 8 hours reading over every line of code looking for conflicts. Don't worry, even if you're going at a project alone, SVN can be very useful to you for backing up your data, so read ahead.&lt;br&gt;
&lt;br&gt;
What I'm here to explain however isn't how SVN works as a whole, but rather how the branch/tags/trunk structure works, and how you can utilize it to make sure you always have good working copies of your code readily available. What you don't want to find is that you've completely muddled up your code, and you can't figure out how to backtrack to the last working copy you had. That's where SVN comes in.&lt;br&gt;
&lt;br&gt;
We're going to start of first with the branch. You can think of this like your workshop. This is where you'll want to start leaving your project between times you're working on it for simple backup purposes, and to show other developers what you are working on. You'll be working mostly from in here, so you'll likely have a couple folders and a bunch of random scraps of coding. This is normal. Once you get to a point where you compile your code, you run it, it seems to work okay, everything checks out. Maybe not all of the features work yet, but it is functioning without any errors at compile or run time. Time to move onto the next step. Tag it, and bag it.&lt;br&gt;
&lt;br&gt;
Now that you have a working copy of your program, you're going to want to stamp it as a working version for future reference, a way for you to say that you've got a working copy, and if everything quite literally hits the fan, you can jump back to this version and know that you're starting on solid footing. Here is where you're going to want to commit what you have to the tags as a version number, like ProjectName v0.01 so you have some kind of incentive to what it is, as well as the repository(SVN) will order them by the number.&lt;br&gt;
&lt;br&gt;
Once you've completed that step, you're going to want to commit it once again into the trunk. The trunk is your most recent working copy of the program. While you may have many tags of the program working for different versions, the trunk will always contain the most recent up to date working copy. Giving a new developer a good starting point to jump into the project, as they'll have the most recent copy to start from.&lt;br&gt;
&lt;br&gt;
In short, to sum up what the previous paragraphs have just said, The most common SVN structure is the branch, tags, and trunk method. Branches are where your in development code is for the project. Tags are where version numbers of your working copies of the program go, and the trunk is where your most recent copy of the program in a working state goes. You can always download the trunk for the most recent working copy, or grab an older working version from the tags.&lt;br&gt;
&lt;br&gt;
Using this method should greatly help you to keep your project managed, and greatly prevent you from losing your project, or ending up with an unrepairable copy. As well as making a group project a lot easier to maintain, from the prevention of one members code overwriting another.&lt;br&gt;
&lt;br&gt;
I hope this helps you, and perhaps steers you towards using SVN in the future. I started using it, and have loved it ever since. Thanks for reading.</description>
        </item>
                <item>
            <title>Project management: Your role</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=107050</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=107050</guid>
            <pubDate>Sat, 15 Jan 2011 19:00:42 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=107050#comments</comments>
            
            <description>Project management is a pretty tiring job, if you want to actually do it right. But just what DOES a project manager do?&lt;br&gt;
&lt;br&gt;
Essentially, a project manager is a facilitator. Your job as a project manager is first and foremost to make sure everything is going to plan, and the project (the game you are making etc) is progressing happily. In games development, your big resource (and so big thing to manage) is your people.&lt;br&gt;
&lt;br&gt;
Here's an important fact to get you started, which a lot of people seem to overlook when managing games development on BYOND: &lt;b&gt;Your people want to do well.&lt;/b&gt; They honest to goodness do! People like working on projects that are going somewhere, to feel their work will be part of a bigger success, so they want the game to succeed.&lt;br&gt;
&lt;br&gt;
With that in mind, your job most probably doesn't involve a lot of shouting at people or strong-arming them into doing things. If you find yourself doing that, something has gone badly wrong and you better review what you're shouting about.&lt;br&gt;
&lt;br&gt;
So the question is, what DO you do? Find out what's holding them back. It might be some confusion on the system they are trying to implement, they may be worrying about how complex it'll be, they may be waiting on some art to get things going, or work from another programmer. Who knows, it may even be some rubbish school homework they need to do, or their girlfriend is upset with them about something.&lt;br&gt;
&lt;br&gt;
Then your job is to remove those problems for them. Worried about how complex a system will be? Simplify the task for them. Waiting on art? Chase the artist for a status update, re-assign the programmer onto something else if you can. It's all pretty straight-forward problem-solving if you think about it.&lt;br&gt;
&lt;br&gt;
Essentially, that really is all a project manager does, solves team and planning problems. An interesting thing emerges though, that is worth bearing in mind for attitude purposes. You decide the way forward, but you're not actually in charge. You spend most of your time solving issues for the team regarding how things are ordered, how much they need to do currently, keeping them re-assured and moving. Or basically, you serve your team, just like the programmer serves the artist's role sometimes and vice versa to progress.&lt;br&gt;
&lt;br&gt;
Once you get that attitude covered, it's all just estimates and listening to your team members. Part two of this set of articles will cover estimation, and three will cover team communication. We will wrap things up with a part four, covering case studies of actual projects and how their project managers handled things.&lt;br&gt;
&lt;br&gt;
I hope this gets you thinking about your team, thank you for reading.</description>
        </item>
                <item>
            <title>Subversion: Improve your teamwork</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=104906</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=104906</guid>
            <pubDate>Wed, 24 Nov 2010 13:41:47 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=104906#comments</comments>
            
            <description>How many times have you made a change to a project you are working on, only to realise it isn't what you wanted, and you have no backup? It's pretty frustrating, isn't it. So you come up with all these fancy backup strategies to try and avoid that, but still from time to time it happens. You just don't backup at the right time, or you lose a backup.&lt;br&gt;
&lt;br&gt;
Personally I had a beautiful example back when I was in university. As a part of my thesis, I was to develop a peer to peer networked program in Java, from the ground up. This meant designing the protocol, deciding on the concept of who shares what with who, identification, performance testing, the works. Without meaning to blow my own trumpet, my implementation was pretty respectable for a university student. I demo'd the system to my supervisor, wrote up my thesis, submitted it.&lt;br&gt;
&lt;br&gt;
&quot;Looks okay so far. Can you provide the source code on CD with this?&quot; Yeah sure no problem I'll just ... where is it? It was just meant to be here, on my nice and stable server ... that I'd reformatted ... *sheds a manly tear*&lt;br&gt;
&lt;br&gt;
Without my source code, my submission would be invalid, and my thesis ruined. Not least, imagine if I spotted a bug before the final demo, what then? Thankfully for me, Java is reasonably simple to de-compile. After 4 days of code clean-up from the disassembly, my lesson had truly been learned, I must use a better system. But surely this is a common problem, surely there is a better solution already out there?&lt;br&gt;
&lt;br&gt;
There is: revision control. Revision control is really simple in concept. You have a file on a server, you make changes locally. You compare the two files, and the server stores the differences, and says &quot;I have version 2 of this file now&quot;. Rinse, and repeat. What if you mess up? Ask the server for the previous version, no harm no foul eh?&lt;br&gt;
&lt;br&gt;
There's another concept at work here, which applies for teamwork: locking. Say you have two team-members, and a server. Team member A wants to edit the file, so they lock it on the server. Team member B can happily view the file and use it locally, edit it locally, but they can't send any changes to the server for it. A is now free to edit without worrying about destroying a version he never received, and commits to the server.&lt;br&gt;
&lt;br&gt;
What about B? B pulls the updated version, and a &quot;conflict&quot; arises. If he's lucky, the software will just merge the changes in, he gets the update AND keeps his changes. Otherwise, he compares the server version side-by-side against his own, and corrects the local version until it's suitable, and says &quot;okay, conflict resolved&quot;. He's now free to send his version to the server. No need to coordinate in advance, just lock and go, then everyone knows what you're changing. They don't even have to avoid that file, they can resolve a conflict before they finish up.&lt;br&gt;
&lt;br&gt;
&quot;This is magic, Stephen! Where do I start?&quot; Well, first you need to pick a tool. This is a pretty big topic, so I'll give you a hand: Subversion&lt;br&gt;
&lt;br&gt;
To interact with a server, you may want TortoiseSVN &lt;a href=&quot;http://tortoisesvn.net/downloads&quot;&gt;http://tortoisesvn.net/downloads&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
For the server, you could run your own. Instead though, I recommend you give a free service a go, such as ... Google Code perhaps? &lt;a href=&quot;http://code.google.com/hosting/createProject&quot;&gt;http://code.google.com/hosting/createProject&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
Both websites have a little documentation on tool use. I will follow this up with an article on subversion specifically, using these tools and services, for a more in depth tutorial on the matter.&lt;br&gt;
&lt;br&gt;
Thank you for reading.</description>
        </item>
                <item>
            <title>F_Damage 1.0.0 Released</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=104282</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=104282</guid>
            <pubDate>Sun, 07 Nov 2010 02:52:21 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=104282#comments</comments>
            
            <description>I notice that for my 0.9.0 release, I had provided a download URL that actually did not work for a lot of people, my apologies. This has now been fixed an verified.&lt;br&gt;
&lt;br&gt;
As I had received no bug reports (possibly due to the aforementioned fault on my part) and have completed a documentation.html file, provided in the ZIP, 1.0.0 is now released. Given the scope of the libraary, all future releases will be bug fix or performance enhancement releases, and of course any changes required to keep things in line with new BYOND functionality.&lt;br&gt;
&lt;br&gt;
F_Damage 1.0.0 already supports displaying on big atoms, it is these kinds of changes that I expect should make up most of future releases. If you do have any issues (including problems just using the library), please post them here:&lt;br&gt;
&lt;a href=&quot;https://code.google.com/p/f-damage/issues/list&quot;&gt;https://code.google.com/p/f-damage/issues/list&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
Unrelated, but I didn't realise you couldn't show HTML as the starting file. Bit of a shame, really, as libraries could use that feature well. Ah well, happy developing!&lt;br&gt;
&lt;br&gt;
Thank you for your time.</description>
        </item>
                <item>
            <title>F_Damage 0.9.0 Released</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=103992</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=103992</guid>
            <pubDate>Sun, 31 Oct 2010 16:35:02 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=103992#comments</comments>
            
            <description>I have released the drop-in update of &lt;a href=&quot;http://www.byond.com/members/Flick&quot;&gt;Flick's&lt;/a&gt; F_Damage library.&lt;br&gt;
&lt;br&gt;
The update is available here:&lt;br&gt;
&lt;a href=&quot;http://www.byond.com/developer/Stephen001/F_Damage&quot;&gt;http://www.byond.com/developer/Stephen001/F_Damage&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
The library provides the following improvements:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Blended icons are cached, resulting in a performance improvement for repeated calls of the same colour. My personal tests seem to suggest uncached calls take ~20 ms, and cached (repeated) calls take ~4 ms subsequently.&lt;/li&gt;

&lt;li&gt;F_Damage will now attempt to centre the icon for any target pixel width and height, not just 32x32 pixel targets.&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
To install the library, simply download it via the pager or as a ZIP file, and in DreamMaker unselect Flick's F_Damage, and select Stephen001's F_Damage. It should be as simple as that.&lt;br&gt;
&lt;br&gt;
If you have any issues, please report them to the issues list:&lt;br&gt;
&lt;a href=&quot;https://code.google.com/p/f-damage/issues/list&quot;&gt;https://code.google.com/p/f-damage/issues/list&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
Once I have completed documentation updates and the error reporting and tracing functions, this will be pushed to a 1.0.0 release. A little time will be left for bug reporting and fixing before doing this.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;What is F_Damage?&lt;/b&gt;&lt;br&gt;
F_Damage is a library that allows a programmer to display &quot;damage taken / healing done&quot; text above a target atom's head, like in a lot of popular RPGs and classic Action games. The library was initially created by Flick, as a more functionally rich replacement of a similar library, S_Damage.&lt;br&gt;
&lt;br&gt;
This F_Damage library is now maintained by Stephen001, with the aim of providing easy to integrate enhancements and personal support for bugs. Rest assured that this library is mature (used in many existing BYOND RPG projects), and will be maintained actively for some time to come, making it the preferred means of displaying damage stats on players / enemies.</description>
        </item>
                <item>
            <title>How do you track your source code?</title>
            <link>http://www.byond.com/members/DevTalk?command=view_post&amp;post=103942</link>
            <guid>http://www.byond.com/members/DevTalk?command=view_post&amp;post=103942</guid>
            <pubDate>Sat, 30 Oct 2010 19:21:18 +0000</pubDate>
            
            <comments>http://www.byond.com/members/DevTalk?command=view_comments&amp;post=103942#comments</comments>
            
            <description>For the interest of developers of supporting tools for BYOND, and looking into currently accepted practices, I have posted this poll. The main aim of this poll is to establish how source code is currently controlled by various developers on BYOND.&lt;br&gt;
&lt;br&gt;
If you use multiple mechanisms for differing projects, please select the option that best demonstrates your preferred or most used mechanism. For the sake of useful results, I have decided to group certain proprietory mechanisms into general types:&lt;br&gt;
&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Local PC Only - You have no cause to share most of your projects, and they exist on the local system only.&lt;/li&gt;

&lt;li&gt;Private Remote Storage - You again have no need to share the code, but have opted for an off-site backup solution. Self-sent emails and private locations on hosting you only have access to fit here.&lt;/li&gt;

&lt;li&gt;Shared File Synchronisation Service - This is your DropBox type services, where-by multiple users can &quot;sync&quot; files that are stored centrally on a server.&lt;/li&gt;

&lt;li&gt;Centralised Revision Control - This is your CVS, SVN etc. This option fits both local only deployments, and shared deployments for collaborative work.&lt;/li&gt;

&lt;li&gt;Distributed Revision Control - This is your Git, Mercurial etc. The prime distinction is that these revision control systems have no formal central master copy.&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
&lt;br&gt;
With this information, other developers looking to provide BYOND specific development services can target their products to best fit people's working practices. Thank you for your time and have a good evening.</description>
        </item>
            
    </channel>
</rss>


