Zara – Fast Fashion
How Zara grew into the world's largest fashion retailer
tl;dr
More about Inditex than Zara. The process is ... Fast Fashion
Inditex's 8 Brands
Inditex is the fashion company that owns Zara and many other brands - totaling 8.
- Zara
- Zara Home
- Bershka
- Massimo Dutti
- Oysho
- Stradivarius
- Pull & Bear
- Uterqüe
The Zara template: Trendy and decently made but inexpensive products sold in beautiful, high-end-looking stores.
Inditex rivals: Arcadia Group, H & M, Mango
Process model / innovation
- processing of customer reactions,
- the quick-turnaround design teams,
- the logistics platform
- Mostly outsourced and Spain based industrial process
- Trendiest items are made closest to home so that the production process, from start to finish, takes only two to three weeks.
- Extremely agile - Constant feedback, alter supply based on demand. customer is always determining production
- No advertising. The shops / real estate is the marketing. Invest heavily in beauty, historical appeal and location of its shops
- Zara’s designers are completely anonymous; some would say this is because they are copiers rather than designers.
Impact
Stock is always fresh. This process has changed consumer behavior. In Zara, everything is a impulse buy - it is good and cheap - so no need to save for a leather jacket.
“With Zara, you know that if you don’t buy it, right then and there, within 11 days the entire stock will change. You buy it now or never. And because the prices are so low, you buy it now.”
Tidbits
- ...neighborhoods share trends more than countries do...
- You open more and more stores, and you don’t have flexibility of the last-minute response
Project Management learnings
These learning are from the Pearl City Project of PCC of 2012. Some of the learnings I took. Jotting them down before I forget.
By handling a Multi-contract approach there will be huge leverage on slippages.
Difference in IT and other industries
- No visibility on IT industries. So we need this visibility & metrics to measure the visibility.
- Interface requirements might change.
Project Management Essentials
- Align with strategy and stakeholder needs
- Establish clear objectives
- Balance resources with constraints of budget, effort, cost, schedule
- Execute!
Must haves:
- Execution Strategy: Who will do it, What, Where, How
- Execution Plan: When will it be done
- Everything has a design basis. Ask why?
- Do follow books. Lots of paper work. Help project control.
- Build craft centers
- Strengths - Database and Information systems.
- Everything is quantifiable. Metric -> Deviation.
- Keep track of assumptions during the course of project.
Types of contracting
- Cost Plus contracting.
- Unit rate contracting.
Object classification of projects
(What is the content of the project and purpose?)
- Dimensions
- Inherent complexities
- Project span
Briefly about Cloud Computing:
- Data Center Electicity Consumption vs Consumption of Services
- Service consumption is seasonal and bursty
- If infrastructure provisioning is minimal, then building the team is going to be important.
- Re-engineering AppStack modules to SOA
- Every App Developer is a System / Service Integrator
- Utility model ala electricity
- Objective is to be lean and mean & to optimize costs
Global Delivery Model #toread
What are imaginary numbers?
The complex numbers allow us to consider scalings and rotations as two instances of the same thing; and by ensuring that negative reals have square roots, we get something where every (non-constant) polynomial equation can be solved: C is the algebraic closure of R.
Quora and StackExchange are fast turning out to be my personalized wikipedia. Unlike the sterilized quality of answers in wikipedia, the learned folks on Quora and SE reaching into their experience and sharing their personable answers, it is (they are) fast becoming my personal treasure trove of knowledge.
Water water everywhere…
Away from the regular posts that I have, this is a simple infographic that came my way. And given its such a neatly presented work I decided to post it here. Of course, I would have loved it if this was a movie in itself (and Meika you must really make this into a small movie, with a sound and all... kids will love it).
I do think infographics are about the wisdom shown with pictures. This one about the oceans is a story in itself.
Caution: Links to a Biiiiig image below... But a definitely very useful and informative one.
Hat Tip: Meika Jensen, Masters Degree.net
Created by: MastersDegree.net
Bloodbath in Genres
From here...
Kano Model
- threshold (or 'requirement'),
- linear (or 'feature') and
- delightful (or 'delight')
Ultimately many attributes transition from delight to feature to requirement as customer expectations raise. This is why in games specifically genres often become an arms race between a few key players.
Quite clearly, the model of things has this transition where features in a product change from being a novelty to a must have by the next iteration of the product. Any marketplace, which has a set of players whose features are a differentiating factor - and any factor being a major differentiator will be assimilated inside the products of all the competitors over a period of time. No wonder, the patents are looked as a potential trump card to stop this transition.
Table Helper in PHP
Custom built frameworks are always a zero-sum game. You get the freedom to build the framework completely suited to your business needs, but then you will more or less have to retread the bug ridden path of other frameworks. For our company currently, as an architect I have immense freedom to look at application from completely 'techie' viewpoint and keep building better and simpler solutions to make the lives of ouri developers a bit simpler.
PHP is an amazingly simple language to build webapps in. Though personally I am in favor of Python or even Ruby to build webapplications, the amount of workforce in PHP available in the market makes it an immensely favored language.
Anyways, back in my work, we have this interesting problem where we have to render hundreds of analytics reports. Pull from the DB and display the results in table format. To deal with this tedium of having to write innumerable presentation layer files to deal with table rendering we use a small function to render the tables. Its a pretty simple function that formats the data in neat table cells using
and encloses each of the resultset in the table rows.
. However, because of this limitation we had the presentation layer tainting the data with the presentation tags.
Hence the genesis of this unit test code.
require 'table_helper.lib.php'; ################# FOR UNIT TESTING THE FUNCTION ####################### function url_logos($profile_id) { switch($profile_id) { case 1: return "abcde"; break; case 2: return "vwxyz"; break; default: return "NONE"; break; } } $Data = array( array('john', 'john carmack', 1, 75, '2008-12-1 00:0:00'), array('galt', 'john galt', 2, 2, '2008-06-06 06:06:06'), array('dagny', 'dagny taggart', 1, 180, '2008-11-00 00:0:00'), array('hank', 'hank rearden', 2, 200, '2008-06-02 06:06:06'), array('roark', 'howard roark', 1, 0, '2008-12-1 00:0:00'), array('john', 'john carmack', 1, 75, '2008-12-1 00:0:00'), ); $Headers = array('Alias', 'Name', 'Profile', 'Games', 'Joining Date', 'Square'); $Templates = array( '"<b>{$data[0]}</b>"', '$data[1]', '"http://www.someurl.com/profile.php?id={$data[2]}&name={$data[0]}"', '"<a href=\"http://www.someurl.com/games/played.do?num={$data[3]}\">{$data[3]}</a>"', '$data[4]', 'url_logos($data[2]);' ); TableHelper::Render($Headers, $Templates, $Data); |
This led to the first version of my code for the TableHelper class which would simply use the PHP 'eval()' code the replace the Templates and fill it with data.
class TableHelper { /** * @func Render($Headers, $Templates, $Data, $Prefix = 'data') * @desc renders a table for the given data and the cell templates given. * @param1 $Headers a string array of table column headers * @param2 $Templates string of cell templates. The data bucket should be named * as data in the default case. If you think of any other name be sure * to pass the correct prefix to the function. * @param3 $Data Data to fill the templates with. * @param4 $Prefix Default bucket for row data is 'data'. Can be anything else. * @note This function now builds a template file instead of using eval. */ static function Render($Headers, $Templates, $Data, $Prefix = 'data') { $NumCols = count($Headers); echo '< table>'; echo '< tr>'; foreach ($Headers as $header) echo '< th>'.$header.'< /th>'; echo '< /tr>'; foreach ($Data as $$Prefix) { echo '< tr>'; for ($i = 0; $i < $NumCols; $i++) { eval("\$_cell=\"$Templates[$i]\";"); echo '< td>',$_cell,''; } echo '< /tr>'; } echo ''; } } |
As any seasoned programmer will tell you looking at the code, I was sacrificing speed (lots!) for want of better code separation by using eval(). After days of rumination I decided to use aggressive template caching in pphplace of eval(). And here's the class with the caching mechanism built in...
# BEGIN Section Table Template Caching Section define(CACHED_TEMPLATES_FOLDER, './cache/'); class TableHelper { /** * @func CachedFilePath($Id) * @desc The table template cached file is just named as unique id.tpl.php * in the CACHED_TEMPLATES_FOLDER folder. */ static function CachedFilePath($Id) { return CACHED_TEMPLATES_FOLDER.$Id.'.html.php'; } /** * @func BuildTemplate($Id, $Headers, $Templates) * @desc Generates the php code for rendering the table and writes the * table generation view code template to the cached folder. */ static function BuildTemplate($Id, $Headers, $Templates) { assert(is_writeable(CACHED_TEMPLATES_FOLDER)) or die('Error THL001: Cache Folder has no Write Permissions.'); $str = ''; /* Build the Table Rendering PHP Code String */ $str .= "< table>\n"; $str .= "< tr>\n"; foreach ($Headers as $header) $str .= "< th>$header< /th>\n"; $str .= "< /tr>\n"; $str .= '< ? php foreach ($Data as $$Prefix) { ?>'; $str .= "< tr>\n"; foreach ($Templates as $template) $str .= "< td>< ?= $template ?>< /td>\n"; $str .= "< /tr>\n"; $str .= "< ? php } ?>\n"; $str .= "\n"; $handle = fopen(TableHelper::CachedFilePath($Id), 'w'); fwrite($handle, $str); fclose($handle); return true; } # END Section Table Template Caching Section /** * @func Render($Id, $Headers, $Templates, $Data, $Prefix = 'data') * @ver 1.2 * @desc renders a table for the given data and the cell templates given. * @param1 $Headers a string array of table column headers * @param2 $Templates string of cell templates. The data bucket should be named * as data in the default case. If you think of any other name be sure * to pass the correct prefix to the function. * @param3 $Data Data to fill the templates with. * @param4 $Prefix Default bucket for row data is 'data'. Can be anything else. * @note This function now builds a template file instead of using eval. */ static function Render($Id, $Headers, $Templates, $Data, $Prefix = 'data') { $NumCols = count($Headers); /* Attempt to just include the cached template file for this table */ $cached_file_path = TableHelper::CachedFilePath($Id); if(!file_exists($cached_file_path)) TableHelper::BuildTemplate($Id, $Headers,$Templates); if(file_exists($cached_file_path)) { include_once $cached_file_path; return; } /* If Cached File cannot be created, just do the EVAL way! */ echo '< table>'; echo '< tr>'; foreach ($Headers as $header) echo '< th>'.$header.'< /th>'; echo '< /tr>'; foreach ($Data as $$Prefix) { echo '< tr>'; for ($i = 0; $i < $NumCols; $i++) { eval("\$_cell=\"$Templates[$i]\";"); echo '< td>',$_cell,'< /td>'; } echo '< /tr>'; } echo '< /table>'; } } |
Catches
The only dependency with this code is that you have to create a Apache writeable folder referenced by the CACHED_TEMPLATES_FOLDER. After that its just fun all the way! Also note that the call to the Render in the unit testing class will now have to be supplied a unique Template Id.
TableHelper::Render($Id, $Headers, $Templates, $Data); |
Linux commands output in PHP
My friend Rahul was giving me a demo of their Web UI and a small but nifty feature caught my eye. They had a feature of being able to configure their systems using the Web UI (which is pretty cool in itself!) and the console output from the configuration command in turn would be displayed in a html iFrame. My company has a similar internal tool which does the same but then showing the output in a step-by-step manner would really be a huge help.
Anyways, so cooked up a quick php function for our system. Hope someone finds this snippet useful.
< ?php /** * @func: Executes the command passed to it as argument and prints the * command console output line by line onto the html output stream hence * giving the illusion of having the command executing in the html window itself. */ function html_exec_cmd($cmd) { $proc = popen("($cmd)2>&1", "r"); echo '<pre>'; while(!feof($proc)) { $result = fgets($proc, 100); echo htmlspecialchars($result); flush(); } pclose($proc); echo '</pre>'; } html_exec_cmd('wget yahoo.com'); # sample command. ?> |
Erlang Ring Code
Erlang Ring Benchmark Problem:
In the Programming Erlang book by Joe Armstrong, we find this problem at the end of the Concurrent Programming chapter.
Write a ring benchmark. Create N processes in a ring. Send a message round the ring M times so that a total of N * M messages get sent. Time how long this takes for different values of N and M. Write a similar program in some other programming language you are familiar with. Compare the results. Write a blog, and publish the results on the Internet!
My contribution to the already growing list of Erlang Ring Benchmark problem. However this is just the code for the Erlang, a N ring setup and M messages moving around the ring in parallel.
Moved to WP 2.5.1
Finally moved the site to WordPress 2.5.1. My own personal blog has been on wordpress.com and that UI was quite inspiring. Now I stand inspired. And definitely the ease with which WP upgrades is quite awesome. However it would have been even greater if I could just upgrade by clicking on a button without even having to download, upload files!
Multiuser Chat using Flex and Ruby
For the last few days I had been googling for some good help for coding networked flash applications for a pet project of mine. Mostly using Flex & Ruby. There have been quite a few I saw - made with flash and using Java; but nothing to my personal liking. And hence I set to build a prototype of my own.
Being a coder and a poor (financially & aesthetically & skillfully
) visual designer, I am totally in love with Flex for the visual quality it brings to the flash applications i can build.
Ruby for the beauty it brings to the code; but then the code is only as good as the coder. And for cooking up a quick prototype, no language has been so good of course except for Perl (for me ofcourse).
Multiplayer - thats a tricky question. Flash cannot support P2P (peer-to-peer) applications as yet. So the best choice available is to use a client-server architecture - the good ole' sockets.
Hence using the code from a lot of different places and porting them from other languages, I managed to quickly cook up a Flex multiuser chat application with a ruby backend. Without further ado, into the code.
The server right now runs on the 9999 port of the localhost and the client connects to the same host and port. If you plan to test it on a hosting server, make sure you change the host and the port.
Note: My wordpress code plugin is fucking up the mxml code. For this part you may just download the zip file and use the client.mxml.
The Flex client:
< ?xml version="1.0"?> <mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()"> </mx><mx :Script> < ![CDATA[ import flash.display.Sprite; import flash.net.XMLSocket; import flash.events.Event; import flash.events.DataEvent; import flash.events.IOErrorEvent; import mx.events.CloseEvent; import mx.controls.Alert; public var socket:XMLSocket = new XMLSocket(); private var host:String = "localhost"; private var port:int = 9999; public function init():void { socket.connect(host, port); socket.addEventListener(DataEvent.DATA, onData); socket.addEventListener(Event.CONNECT, onConnect); socket.addEventListener(Event.CLOSE, onClose); socket.addEventListener(IOErrorEvent.IO_ERROR, onEvent); } private function onConnect(event:Event):void { board.htmlText += "<i>Client: Connected to server" + "<br />"; } private function ReconnectHandler(event:CloseEvent):void { if (event.detail == Alert.YES) init(); } private function onClose(event:Event):void { board.htmlText += "<i>Disconnected from server</i>" + "<br />"; Alert.show("Reconnect to the chat?", "Reconnect?", (Alert.YES | Alert.NO), this, ReconnectHandler); } private function onEvent(event:Event):void { board.htmlText += "Error" + "<br />"; trace(event); } private function onData(event:DataEvent):void { board.htmlText += event.text; } private function sendMesg():void { socket.send(username.text+ ': <font color="#' + cp.selectedColor.toString(16) + '">' + mesg.text + "</font>\n"); mesg.text = ""; } ]]> </mx> <mx :Style> .marginstyle { paddingTop:12; paddingBottom:12; paddingLeft: 12; paddingRight: 12; } .spacestyle { paddingTop:2; paddingBottom:2; paddingLeft: 2; paddingRight: 2; } </mx> <mx :Panel title="chatterbox" styleName="marginstyle"> <mx :TextArea editable="false" id="board" text="" height="400" width="600" color="#0000FF" styleName="spacestyle"/> </mx><mx :HBox> <mx :TextArea id="username" text="guest" height="20" width="50%"/> <mx :ColorPicker id="cp" height="20" width="20"/> </mx> <mx :HBox> <mx :TextArea id="mesg" height="50" width="500" styleName="spacestyle"/> <mx :Button label="Send" click="sendMesg()"/> </mx> |
To compile it to a swf
Assuming you already have the free Flex SDK just use
$> mxmlc client.mxml
which will create a client.swf file for you.
Multiuser Ruby chat server:
#!/usr/bin/ruby require 'socket' MSGS = {"init" => "Server started. Waiting for connections...", "welcome" => "Welcome! type EXIT to quit", "byebye" => "Disconnected from server"} EOF = "\000" HOST = "localhost" PORT = 9999 server = TCPServer.new(HOST, PORT) puts MSGS["init"] # array to store all the active connections sessions = [] while (session = server.accept) # push the current session(socket) in the array sessions < < session # initialize a new thead for each connection Thread.new(session) do |local_session| local_session.puts "<i>#{MSGS["welcome"]}" + EOF # each time a client sends some data send it to all the connections while(true) data = local_session.gets if !data.nil? delim_pos = data.index(":") name = data[0..delim_pos-1] data = data[delim_pos+1..-1] if data[0] == EOF data = data[1..-1] elsif data.chomp == "EXIT" sessions.delete(local_session) local_session.puts "<i>#{MSGS["byebye"]}</i>" + EOF local_session.close data = "<i>#{name} disconnected from the server</i>" + EOF end end sessions.each do |s| begin s.puts "<b>#{name}</b>: #{data.chomp}" + EOF rescue Errno::ECONNRESET # an exception is raised, that means the connection to the client is broken sessions.delete(s) end end end end end |
To Run
User ruby chat_server.rb
Source Code: Download here. It contains a simple single user server - java & ruby versions [simpleServer.java & server.rb], a multiuser server [chat_server.rb] and the client [client.mxml].
Anyone, any doubts can leave a comment.
