How to grow a program from a prototype

    Every week on specialized blogs, we read how to use the X methodology and the Y framework to write well-designed and easily maintained software. We are constantly told that supposedly govnokod is bad, refactoring is our everything, they give some very important spherical advice in a vacuum. In most of these articles, one can find abstract philosophical teachings, for example, I’ll print this and hang it at the entrance to the office:


    What if I say that not all projects are the same, and some of them are not that possible, but even need to be carefully grown from the prototype? I spoke about this at the Unite'12 conference , and now I will tell you.

    Introduction


    The idea of ​​writing this text was gathering dust in my head for a very long time. But yesterday’s article under the heading “Why you can’t turn a prototype into a final program ” suddenly became a real catalyst . It turns out that I suddenly can’t do what I have been doing successfully for two years and am proud of it.

    While the disgruntled reader did not begin to quickly scroll down to be the first to write a comment and tell me how wrong I am, I want to point out one fact that (for some reason) many ignore - all projects are different! If you make enterprise applications, this does not mean that no one writes embedded systems, ups for smartphones or one-time presentations.

    Hence the manifestations of a furious holivor in the comments to any similar post. So, let me first talk about the specifics of the projects that I usually do.

    Projects


    I work for Interactive Lab . Basically, we do offline interactive installations, the creation of software for which is very different from conventional software development:

    • There is no clear TK ( here's the show, do it cool! ),
    • All projects are small, but very different ( completely different, not “in that project we used mysql, and in this we will use mongodb - you will have to LOAD the CODE!” ),
    • Very short deadlines that cannot be rescheduled ( “sorry, we don’t have time, please transfer Atom Expo to a month or two” ),
    • Often only 1 day is working during the exhibition, and then they are thrown out ( update : but, at the same time, the code must be clear in order to correct it if something suddenly breaks an hour before the deadline ),
    • The combination of software and special hardware,
    • Full control over the hardware ( slows down? Optimize? Why are you, let's go buy gtx 690 ).

    So, I’m sitting in the office, I’m not touching anyone, I’m reading Habr, there I eat peach ... And then the boss comes up to me and asks a question that, in general terms, boils down to the following: “Valentin Vladimirovich, how long does it take for you to do such a thing which we never did and vaguely imagine how to do it? .. Mmm, two weeks, right? ” Well, then it turns out that some kind of event in three weeks, the client “doesn’t know what exactly, but wants it very cool to have everything”, there are no assets, ideas are also not very special ...

    Process


    The principle of iterative development is not new at all, and hundreds of articles have been devoted to it, including on Habré. How is it, Agile evangelists say? We take, then, a fichelist, see what we can do for an iteration, say, in two weeks. We do it. We look again ...

    So, stop! Fichelist? We have neither TK nor a clear idea of ​​what this should be. Iteration in two weeks? We have only 15 working days, what two weeks, what are you !?

    This is how we arrived at the following algorithm:

    1. Brainstorm ideas.
    2. The most simple and fast prototype with test assets in a day or two.
    3. Target Iron Test.
    4. Absolute sucks? GOTO 1.
    5. It seems not bad, but something needs to be changed / added.
    6. Update the prototype in a day.
    7. If not deadline yet - GOTO 3.
    8. We fall asleep.

    As you can see, iterations for 1-2 days prototype grows in the final application. And it works great.

    After going through the eyes of the algorithm, following the cycle a couple of times and exiting it, you can immediately imagine its obvious advantages:

    • The concept is created iteratively with feedback from the prototype. There is no need to write an exhaustive TOR before starting work, which still does not guarantee the success of the original idea.
    • How good a concept can be seen in the first two days. There is nothing more unpleasant than understanding the day before the deadline that the whole idea sucks completely.
    • Closer to the deadline there is always a ready-made application. It does not have all the features, it is not beautiful enough, but it can already be put on the exhibition. There simply cannot be anything that is ready for us.
    • All the nuances of a bunch of software + hardware can be found out immediately at the stage of the first iterations. If you think that on 9 screens and 5 video cards with a total resolution of 4098x2304 your application will work the same way as on an office FullHD monitor, you are very mistaken.
    • Having played with the prototype, there is no need to rewrite everything * with a more correct code * into the final application. The prototype itself will be the application.


    Prototype


    For some reason, in most articles about prototypes they speak of something temporary, vile, sticky and unpleasant. Like, unscrupulous developers wind up new features on a careless prototype, turning it into a Frankenstein monster. And the main conclusion is that everything must be rewritten, and happiness will come!



    Sometimes they ask me a reproachful question: “Aren't you ashamed of the code of your application, which turned out to be a gradual upgrade of the prototype?”. Honestly, I am ashamed of all my code that I wrote more than a month ago. Why? Because over the past month, including while this code was written, I personally grew up as a developer. And today's I would have written everything in a completely different way. Well, tomorrow I would really like to rewrite all this to hell! Therefore, every time I smile dirty when I hear offers to take and rewrite everything again.

    Let us think of the prototype as a tree that should bloom and bear fruit by a certain time. It depends only on us it will bloom roses and sugar peaches will grow on it, or it will suddenly be covered with killer flowers, and we, as the culprits of all this outrage, will be put with a sword to chop them. At the same time, as in a fairy tale, two new ones grow in place of a felled one. I think everyone has already understood the metaphor.

    In general, the convergence of the written code to the shit with the number of lines n> N is highly dependent on the individual. If your programmer sculpts tentacles to a prototype tree without really worrying about his future, why do you think that after rewriting everything, he will not asymptotically converge at the end to a similar result?



    To do, simply, you need everything right. It’s good to imagine that this is not a prototype for release, but a living organism, which will greatly change from your actions at the sprout stage, having grown into its final form. And this form can be STRONGLY different from what you laid in its genotype at startup.

    And just as your grandmother, in her small garden outside the city, pulls grass around the sprouts, cuts them, grafts some varieties onto others, so you should carefully monitor your prototype as it grows. This is what distinguishes a good programmer from a bad one. A good programmer sees where his code grows, what needs to be done now so that later you don’t have to cut dead branches; understands how to carefully get rid of beetles terrorizing a tree; knows when to fence it so that it grows in the right direction.

    KISS, DRY, OOP, design and other extremes


    If I were given 10 rubles for each article that mentions KISS or DRY , I would have long ago bought the BMW 3 I’m dreaming of. These buzzwords have already stuck a terrible OOP in their belt, on which The Gang of Four is sitting and whipping it with design patterns (the same picture, of course).

    All that matters is whether a person can grow a healthy tree from a prototype.

    Specifically, in our realities, everything, moreover, needs to be done also very quickly. Iterations a day or two, no more. So you begin to fight with unauthorized interpretations of KISS, DRY and all sorts of OOP brain. Which, frankly, does not always work.

    It's like, excuse me, with the Russian Orthodox Church. Experienced priests, theologians and historians of religion, go and know why this particular rite is just like that, although it looks very strange from the outside. But ask any of 97% of the remaining believers - you will get the answer, they say, do as they said and you will be saved. And well, if not beaten.

    And KISS, and DRY, OOP ... what else is there? Designing all. These are all good concepts, but trembling takes when you see how they are applied in life. And you understand that such an application with growing a prototype is compatible a little less than nothing. Hence the terrible lame trees with cannibalistic flowers.

    Especially when a person throws on extreme situations. If it’s OOP, then 100500 abstract classes are required and for each interface, and in order to create something specific, you need to do this through a special factory of builder factories. But sheer DRY. Everything is mega-abstract and no code repeats. And it doesn’t bother anyone that in order to achieve all this, it took 20 times more code to write. But IoC with DI also needs to be configured so that no one can understand where this program starts at all.

    But programmers are people like that, let them only complicate things. You think to grow a prototype of a boiler, and after a week you catch yourself thinking that you are writing a nuclear reactor. And how, damn it, the thought jumped from the boiler to the reactor is no longer clear.

    And KISS, basically, falls into the opposite extreme. Where in the middle of development you understand that everything is so Simple that a branch, generally speaking, a tree can have only one, and there's nothing to be done about it. We throw out the prototype, we say that prototyping sucks and start again.

    So what to do?


    As they usually say in films. “Forget everything you know!”, “To catch a cat, you need to become a cat!” etc. But this is not about us. Do not forget anything. On the contrary, it would be good to remember examples of the extremes of applying all sorts of techniques, so that in a moment of fleeting reflection in time to realize what takes you somewhere wrong.

    But, for some time, the brain will be broken and you will have to beat yourself with a ruler on your hands, of course. Well, we can’t stop thinking abstractly and complicate everything in the head.

    So, what needs to be done so that the prototype tree does not fade? Somewhat at first glance simple principles:

    Very short iterations and feedback
    From the specifics of the project, you need to choose the minimum time for iteration and be sure to run the application at the end of each iteration on the target device / at the target audience. If you are making an interface for a large multi-touch table, do not be lazy, go up to it and poke at the drawn buttons. Are they easy to reach? Is it easy to hit with a thick finger? Of course, everyone can use a mouse on a small screen. Sit down remake!

    Integrity
    Nowadays it is accepted that several programmers work on one project at once. Everyone makes some kind of module. So, important modules should be developed in parallel, developers synchronization should take place as often as possible. Ideally, once per iteration. The goal is to bring all working modules together as soon as possible and see what happened.

    It does not matter at what stage of development the module is now. And if (as usually happens) the integration time has come, and the code is in such a state that nothing from the past ALREADY works, and from the new MORE it does not work, it may shock you, but you can COMMENT on idle places!

    Solving current problems
    Suppose there is a simple task for an hour or two. But, programmers are people like those of a chess player, a game of 64 moves ahead immediately unfolds in the head. It becomes clear that then one has to be done, and for extensibility, the second. In addition, running at 32m already shows that for greater photorealism of balancing the load of miscalculation of physics, you need to start doing the third right now. Anyway, let's write a framework!

    LINE BY HAND !!! And then with legs and feet! Now we solve only current problems. The fastest way. As practice shows, such sweeping features have a high probability of changing dramatically or even completely disappearing.

    Carefully monitor the extremes
    Well, we do everything quickly and stupidly ... NO! Well, you again! Try not to go to extremes and do everything directly completely stupidly. You see where this whole thing will lead you - leave yourself some room for maneuver: neat OOP with no frills, squeeze into the components of state machines, make a little more settings than you need now, refactor a slightly overgrown class. To do everything simply and only what is needed does not necessarily mean producing govnokod. It’s just that some people don’t have a different way.

    Maximum proximity of assets to final
    All assets from the very beginning in terms of basic parameters need to be adjusted as close as possible to the expected ones. Suppose that in the first prototype instead of pictures there will be lolcats from the personal archive of the developer, and instead of the planned FullHD video, the downloaded Iron Man 2 purchased in BluRay quality will be downloaded .

    If you plan to display 100 images, give them exactly 100 (and preferably 150 for reliability), instead of having to test it on the smoothly scrolling three pictures for the whole life of the prototype. And then, with surprise, discover that 100 pictures lag, hang and do not fit into memory.

    ***


    There are a number of minor arrangements that are not so important as to impose their use. Anyway, every team that decides to live and work on similar principles will soon come to its own specific unwritten rules.

    And I just hope that from this article everyone will take something useful for themselves. And that prototype trees will grow, and the word “prototype” itself will lose its negative connotation.

    Updates


    • He added to the description “but, at the same time, the code should be clear in order to correct it, if something suddenly breaks an hour before the deadline” . Because many people paid attention to the lifetime of the installation. BUT! This absolutely does not mean that everyone should put on the quality of the code.

    Also popular now: