789
I Use This!
Very High Activity

News

Analyzed about 18 hours ago. based on code collected 1 day ago.
Posted over 5 years ago
Improving Drupal and Gatsby Integration - The Drupal Modules At weKnow we are not only using Drupal, we also take contributing back very seriously and now is the time for improving the Drupal and Gatsby integration. As mentioned in my ... [More] personal blog, Moving weKnow's personal blog sites from Drupal to GatsbyJS, we have been using Gatsby with Drupal for projects as our decouple strategy lately, and after building a few sites with Drupal and Gatsby we found some challenges, which we resolved writing custom code. But now we’ve decided to share our knowledge as contributed modules. Toast UI Editor This module provides a markdown WYSIWYG editor integration for Toast UI Editor jmolivas Tue, 12/04/2018 - 11:15 [Less]
Posted over 5 years ago
In this article I am going to show you a technique I used recently to mock a relatively simple external service for functional tests in Drupal 8. Imagine the following scenario: you have an API with one or a few endpoints and you write a service ... [More] that handles the interaction with it. For example, one of the methods of this service takes an ID and calls the API in order to return the resource for that ID (using the Guzzle service available in Drupal 8). You then cast the Guzzle response stream to a string and return whatever from there to use in your application. How can you test your application with this kind of requirements? The first thing you can do is unit test your service. In doing so, you can pass to it a mock client that can return whatever you set to it. Guzzle even provides a MockHandler that you can use with the client and specify what you want returned. Fair enough. But what about things like Kernel or Functional tests that need to use your client and make requests to this API? How can you handle this? It’s not a good idea to use the live API endpoint in your tests for a number of reasons. For example, your testing pipeline would depend on an external, unpredictable service which can go down at any moment. Sure, it’s good to catch when this happens but clearly this is not the way to do it. Or you may have a limited amount of requests you can make to the endpoint. All these test runs will burn through your budget. And let’s not forget you need a network connection to run the tests. So let’s see an interesting way of doing this using the Guzzle middleware architecture. Before diving into that, however, let’s cover a few theoretical aspects of this process. Guzzle middlewares A middleware is a piece of functionality that can be added to the pipeline of a process. For example, the process of turning a request into a response. Check out the StackPHP middlewares for a nice intro to this concept. In Guzzle, middlewares are used inside the Guzzle handler stack that is responsible for turning a Guzzle request into a response. In this pipeline, middlewares are organised as part of the HandlerStack object which wraps the base handler that does the job, and are used to augment this pipeline. For example, let’s say a Guzzle client uses the base Curl handler to make the request. We can add a middleware to the handler stack to make changes to the outgoing request or to the incoming response. I highly recommend you read the Guzzle documentation on handlers and middlewares for more information. Guzzle in Drupal 8 Guzzle is the default HTTP client used in Drupal 8 and is exposed as a service (http_client). So whenever we need to make external requests, we just inject that service and we are good to go. This service is instantiated by a ClientFactory that uses the default Guzzle handler stack (with some specific options for Drupal). The handler stack that gets injected into the client is configured by Drupal’s own HandlerStackConfigurator which also registers all the middlewares it finds. Middlewares can be defined in Drupal as tagged services, with the tag http_client_middleware. There is currently only one available to look at as an example, used for the testing framework: TestHttpClientMiddleware. Our OMDb (Open Movie Database) Mock Now that we have an idea about how Guzzle processes a request, let’s see how we can use this to mock requests made to an example API: OMDb. The client Let’s assume a module called omdb which has this simple service that interacts with the OMDb API: client = $client; } /** * Get a movie by ID. * * @param \Drupal\omdb\string $id * * @return \stdClass */ public function getMovie(string $id) { $settings = $this->getSettings(); $url = Url::fromUri($settings['url'], ['query' => ['apiKey' => $settings['key'], 'i' => $id]]); $response = $this->client->get($url->toString()); return json_decode($response->getBody()->__toString()); } /** * Returns the OMDb settings. * * @return array */ protected function getSettings() { return Settings::get('omdb'); } } We inject the http_client (Guzzle) and have a single method that retrieves a single movie from the API by its ID. Please disregard the complete lack of validation and error handling, I tried to keep things simple and to the point. To note, however, is that the API endpoint and key is stored in the settings.php file under the omdb key of $settings. That is if you want to play around with this example. So assuming that we have defined this service inside omdb.services.yml as omdb.client and cleared the cache, we can now use this like so: $client = \Drupal::service('omdb.client'); $movie = $client->getMovie('tt0068646'); Where $movie would become a stdClass representation of the movie The Godfather from the OMDb. The mock Now, let’s assume that we use this client to request movies all over the place in our application and we need to write some Kernel tests that verify that functionality, including the use of this movie data. One option we have is to switch out our OmdbClient client service completely as part of the test, with another one that has the same interface but returns whatever we want. This is ok, but it’s tightly connected to that test. Meaning that we cannot use it elsewhere, such as in Behat tests for example. So let’s explore an alternative way by which we use middlewares to take over any requests made towards the API endpoint and return our own custom responses. The first thing we need to do is create a test module where our middleware will live. This module will, of course, only be enabled during test runs or any time we want to play around with the mocked data. So the module can be called omdb_tests and we can place it inside the tests/module directory of the omdb module. Next, inside the namespace of the test module we can create our middleware which looks like this: getUri(); $settings = Settings::get('omdb'); // API requests to OMDb. if ($uri->getScheme() . '://' . $uri->getHost() . $uri->getPath() === $settings['url']) { return $this->createPromise($request); } // Otherwise, no intervention. We defer to the handler stack. return $handler($request, $options); }; }; } /** * Creates a promise for the OMDb request. * * @param RequestInterface $request * * @return \GuzzleHttp\Promise\PromiseInterface */ protected function createPromise(RequestInterface $request) { $uri = $request->getUri(); $params = \GuzzleHttp\Psr7\parse_query($uri->getQuery()); $id = $params['i']; $path = drupal_get_path('module', 'omdb_tests') . '/responses/movies'; $json = FALSE; if (file_exists("$path/$id.json")) { $json = file_get_contents("$path/$id.json"); } if ($json === FALSE) { $json = file_get_contents("$path/404.json"); } $response = new Response(200, [], $json); return new FulfilledPromise($response); } } Before explaining what all this code does, we need to make sure we register this as a tagged service inside our test module: services: omdb_tests.client_middleware: class: Drupal\omdb_tests\OmdbMiddleware tags: - { name: http_client_middleware } Guzzle middleware services in Drupal have one single (magic) method called __invoke. This is because the service is treated as a callable. What the middleware needs to do is return a (callable) function which gets as a parameter the next handler from the stack that needs to be called. The returned function then has to return another function that takes the RequestInterface and some options as parameters. At this point, we can modify the request. Lastly, this function needs to make a call to that next handler by passing the RequestInterface and options, which in turn will return a PromiseInterface. Take a look at TestHttpClientMiddleware for an example in which Drupal core tampers with the request headers when Guzzle makes requests during test runs. So what are we doing here? We start by defining the first two (callable) functions I mentioned above. In the one which receives the current RequestInterface, we check for the URI of the request to see if it matches the one of our OMDb endpoint. If it doesn’t we simply call the next handler in the stack (which should return a PromiseInterface). If we wanted to alter the response that came back from the next handler(s) in the stack, we could call then() on the PromiseInterface returned by the stack, and pass to it a callback function which receives the ResponseInterface as a parameter. In there we could make the alterations. But alas, we don’t need to do that in our case. A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled. Read this for more information on what promises are and how they work. Now for the good stuff. If the request is made to the OMDb endpoint, we create our own PromiseInterface. And very importantly, we do not call the next handler. Meaning that we break out of the handler stack and skip the other middlewares and the base handler. This way we prevent Guzzle from going to the endpoint and instead have it return our own PromiseInterface. In this example I decided to store a couple of JSON responses for OMDb movies in files located in the responses/movies folder of the test module. In these JSON files, I store actual JSON responses made by the endpoint for given IDs, as well as a catch-all for whenever a missing ID is being requested. And the createPromise() method is responsible for determining which file to load. Depending on your application, you can choose exactly based on what you would like to build the mocked responses. The loaded JSON is then added to a new Response object that can be directly added to the FulfilledPromise object we return. This tells Guzzle that the process is done, the promise has been fulfilled, and there is a response to return. And that is pretty much it. Considerations This is a very simple implementation. The API has many other ways of querying for data and you could extend this to store also lists of movies based on a title keyword search, for example. Anything that serves the needs of the application. Moreover, you can dispatch an event and allow other modules to provide their own resources in JSON format for various types of requests. There are quite a lot of possibilities. Finally, this approach is useful for “simple” APIs such as this one. Once you need to implement things like Oauth or need the service to call back to your application, some more complex mocking will be needed such as a dedicated library and/or containerised application that mocks the production one. But for many such cases in which we read data from an endpoint, we can go far with this approach. [Less]
Posted over 5 years ago
Episode Number:  221 The Drupal 8 Rabbit Hole Module allows you to control what happens when someone views an entity page. Before you ask why this might be important, let me clarify, it's not a layout tool. It's a simple module that allows you to ... [More] easily redirect or prevent users from viewing specific types on entities on your site. Tags:  Drupal Contrib Drupal 8 Site Building Drupal Planet [Less]
Posted over 5 years ago
We’re featuring some of the people in the Drupalverse! This Q&A series highlights some of the individuals you could meet at DrupalCon. Every year, DrupalCon is the largest gathering of people who belong to this community. To celebrate and take ... [More] note of what DrupalCon means to them, we’re featuring an array of perspectives and some fun facts to help you get to know your community. [Less]
Posted over 5 years ago
Direct .mp3 file download. DrupalEasy Podcast 212 - Commerce Guys: decoupling and roadmap Matt Glaman, (mglaman) and Bojan Zivanovic, (bojanz) join Mike live from Disney World to talk about decoupling Drupal Commerce as well as the roadmap for Drupal ... [More] Commerce as a project. We take a quick side trip into some blog posts Matt recently wrote about running all of Drupal core's automated tests in DDEV-Local. Interview Commerce Guys Drupal Commerce project Commerce Guys projects on GitHub Decoupling Drupal Commerce Commerce Cart Flyout module JSON:API module Composer support in Drupal core initiative Commerce Shipping Matt's blog posts related to running Drupal's automated tests with DDEV: Nightwatch, FunctionalJavascript, PHPUnit. Snowboard wrist guards Three Colors: Blue DrupalEasy News Drupal Career Online - the 12-week (3 half-days/week) best-practice focused training program begins February 25, 2019. Learn more at one of our free Taste of Drupal webinars (December 17, January 9, February 6, February 20). Professional local development with DDEV - 2-hour, hands-on, online workshop held monthly (December 12). Local Web Development with DDEV Explained - new book from Mike! Upcoming events Florida DrupalCamp 2019 - Feb 15-17 - registration and session proposals now open. Sponsors Drupal Aid - Drupal support and maintenance services. Get unlimited support, monthly maintenance, and unlimited small jobs starting at $99/mo. WebEnabled.com - devPanel. Follow us on Twitter @drupaleasy @ultimike @bojan_zivanovic @nmdmatt Subscribe Subscribe to our podcast on iTunes, Google Play or Miro. Listen to our podcast on Stitcher. If you'd like to leave us a voicemail, call 321-396-2340. Please keep in mind that we might play your voicemail during one of our future podcasts. Feel free to call in with suggestions, rants, questions, or corrections. If you'd rather just send us an email, please use our contact page. [Less]
Posted over 5 years ago
On a recent project, I needed to add some behavioral tests to cover the functionality of the Password Policy module. I seem to be a sucker for pain, because often I choose to test the things it seems there's no documentation on—like testing the ... [More] functionality of the partially-Javascript-powered password fields on the user account forms. In this case, I was presented with two challenges: I needed to run one scenario where a user edits his/her own password, and must follow the site's configured password policy. I needed to run another scenario where an admin creates a new user account, and must follow the site's configured password policy for the created user's password. So I came up with the following scenarios: [Less]
Posted over 5 years ago
I used to draw a lot. I never thought of myself as a good artist, but I felt like I had a knack for replicating images, so I turned into a game. I’d say, “let’s see if I can take this small cell from my favorite comic and blow it up into a larger ... [More] version of itself.” Take this for example: Alita as drawn by Amy It came as no surprise to me when I became obsessed with creating responsively pixel perfect websites that represented our talented design team’s work precisely. There was a problem, however. Up until recently front end developers didn’t have a great way to create responsive grids, so we used the tools that we had readily available to us. For example, if you intend to bake chocolate chip cookies with carob, the result is going to be wildly different than if you used chocolate chips! (Carob is never a replacement for chocolate, I don’t care what you say…) Let’s review our options in the evolutionary order we received them: Tables: Tables were originally intended for tabular data created through HTML and nothing more. Floats: Since the web was inspired by print, floats were created to successfully wrap text around images. Floats used with inline elements, and specified widths and gutters, have been used for years to create grids. In addition, all browsers support floats. The problem, however, is they can be complex, prone to break, and often contain tricky clearing and nth item margin removal between responsive breakpoints. In other words, it’s a lot of work. Flexbox: As browsers became more supportive of flexbox, many of us got tremendously excited. Flexbox was designed with rows and columns in mind, including created elements within rows and columns that have equal heights and widths. Vertical centering has never been easier, but that’s a whole other blog post. Flex-wrap made it possible for front end devs to create grids using flexbox, so we kissed floated grids goodbye. Grid Layout: Low and behold, a CSS solution made with grid styling in mind - finally! As soon as this became widely browser compatible, I jumped at the opportunity to add this to a brand new project implementation. First things first… after being part of a handful of new site builds from start to finish, it quickly became apparent how important establishing global site containers were at the foundational level. That’s when I created this visual guide: The Full Screen width is as far as the screen allows. This assumes the site could stretch to infinity, if we had a screen that would allow for that. But we don’t. So, the site boundaries need to be established to something more reasonable. The Site Max Width limits how wide the website itself is willing to stretch. In the instance I’ll be talking about, a width of 3000px was set on the tag and centered using margin-left: auto; and margin-right: auto;. Full-site width elements would live here including but not limited to background images that stretch the full width of the site. The Content Side Padding always exists, regardless of device. It creates left/right spacing in between elements we don’t want touching the very edge of the screen, and the edge of screen itself. An example of this would be text elements. The Grid area is where design-determined columns start and end. Designers typically imagine 12-columns when crafting websites, though the total columns can vary. Planning the full grid area pixel width with a designer right at the beginning is crucial for creating precisely planned grid walls, and perfectly centered elements. Grid Layout also makes creating sidebars super easy to create and maintain as well. In order to make Grid Layout compatible with IE, it was necessary to add a polyfill to the project. We’re using npm, so a dependency was added like so to the package.json file, and npm update was run to update the package-lock.json file. Next up, create the grid: You’re going to see a lot of Sass variables in these code examples, so this might provide a bit of context. (Note: This is a simplified version. This project in particular has 4 grid columns on mobile, and 16 on extra large screens. There were a number of media queries needed to be taken into account too): After creating the global grid, it dawned on me that I could create a visual grid fairly easily so my team and I could check our work against the exact line assignments. The idea came to me after I saw my teammate, Marlene, apply a Neat (of Bourbon and Neat CSS libraries) visual-grid to a previous project. So, I added a bit of markup to the html.html.twig template: My tech lead, Maria, loved the idea so she came up with a quick way for us to see the visual grid using a preprocess hook in the .theme file. All the team needed to do was apply ?show-grid=1 to the end of any of the site’s urls to check our work and see if it lined up: Of course, it had to inherit the overall .grid properties (code shown above), in addition to containing its own unique styling, in order to superimpose the visual grid over the top of the entire page. The visual grid looked like this when we were working on our project: Given that applying CSS Grid Layout to a project was a new experience for me and my team, a couple things needed to happen: Create documentation Meet with the team to explain how I’ve setup the project, Encourage innovation and communication, and Go over the documentation Encourage updates to the documentation when new tools have been created, and report back to the rest of the team It was important for the team to know my intentions for applying the horizontal containers and the use of CSS Grid Layout, and to admit that this is new territory and I was relying on all of us to be on the same page, applying the tools in the same way, and finding ways to make our jobs easier and more efficient. Initially, we started using CSS Grid Layout for specifically layout purposes of an element’s parent wrapper. We are all well versed in Flexbox now, so we applied Flexbox on the child element rows like so: Later, I discovered a way to generically place child elements into a grid parent without needing to assign each child element a place inside the grid. Check out my Codepen example to see how this might work. Many of the elements on the site needed grid to be applied first. However these elements needed to be centered as well, like the elements in the screenshot above. CSS Grid Layout comes with a property grid-column that takes two arguments: 1. a start column and 2. an end column. It needed to be IE compatible, so I whipped up this little mixin: It took my team some acclimating to enter start and end column values for every element in every breakpoint necessary. Admittedly, it was a bit of a mind-bender at times. This especially took some getting used to since applying grid to a parent element will render all its children into a single column out of the box. It wasn’t long before this grid centering code appeared in the project, thanks to innovative thinking from Maria, Marlene, and Jules: With that, a themer simply enters how many columns the centered element is wide and how many columns exist on the grid at that breakpoint. Voila, centered grid elements in no time flat! I could go on and on, there’s so much to share. Though designs may have adjusted slightly over the course of the project, the layout and overall elements largely stayed the same. My ultimate goal was to create an exact replication of our designer, Vicki’s, beautiful work. But, I couldn’t do this all by myself. I needed my teammates to be on the same page. And, that they were! Here’s an example of a page I did very little work on. This is also an example of using CSS Grid Layout with a sidebar element with a 12-column across element in the middle of listing items that needed to be placed in fewer columns. One of these screenshots is the design and one is the live site. Can you tell which is which? This whole experience truly was a team effort. The code snippets I’ve shared with you did not look like that at the beginning. They evolved overtime, and have grown much more beyond the foundation I originally envisioned. To my surprise, my team got so excited about these tools of precision that they helped produce robust mixins, setting global spacing variables. Say our designer wants to change the gutter from 16px to 20px. No problem, change the $grid-gutter variable and all of the elements across the site just fall in line. No more changing every spacing instance of every element across the site. Goodbye frustration, hello efficiency and perfection! So, if you find you’re as obsessed as I am with creating a pixel perfect responsive experience for your websites, or if you simply want to start using CSS Grid Layout with purpose in your next project, please feel free to adapt these tools into your practice. Thanks for taking this journey with me, and I hope you look forward to the next blog posts of this series where my teammates discuss other problems we solved in this implementation. Isn’t nerding out with other passionate people the best?! [Less]
Posted over 5 years ago
Architecting your own Drupal site with Layout Builder Shankar Sat, 12/01/2018 - 08:07 Having a routine of reading newspaper early in the morning is an intricate tapestry. We need something more to continue with our engagement with a ... [More] newspaper day after day as we aren’t vessels of information. And that elusive thing is not just the pleasure of words but an engrossing design. So, when the editors make the prose readable, graphic designers work on creating templates that help in sustaining our interest in the act of reading. Similarly, site builders and content authors require intuitive tools as well for developing pages, alter layouts and add or arrange blocks with live preview. Hence, when it comes to new and refreshing easy-to-use page builders, An ambitious visual design tool called Layout Builder is on its way to change things completely. Layout Initiative: The inception Layout Builder took its birth through Layout Initiative which was started with the objectives of: Underlying APIs for supporting layout management to be utilised by core and contributed projects alike. Offering a drag and drop interface for building layouts that can apply both to overall site sections and overridden on separate landing pages. Allowing the layout application to data entry forms and content Layouts have been a significant tool in component-based theming as they can be utilised to map data to component templates. In Drupal 8.3, the Layout API and the Layout Discovery module were included as an experimental subsystem. They were stabilised in Drupal 8.4. Layout Builder is being planned to be stabilised in Drupal 8.7 The Layout API and the Layout Discovery module were added in Drupal 8.3 as an experimental subsystem, and they were stabilized in Drupal 8.4. An experimental Layout Builder module was included in Drupal 8.5 and is being planned to be stabilised in Drupal 8.7. Layout Builder: A guile approach to site building Layout Builder offers the ability to customise the layout of your content where you start by choosing predefined layouts for different sections of the page and then populate those layouts with one or more blocks. That is, it gives you a UI with a visual preview and supports using multiple layouts together. It lets you place blocks in layout regions and create layouts for separate pieces of content. Layout Builder gives you a UI with a visual preview and supports using multiple layouts together. At present, there are some Drupal modules that can enable the functionality of Layout Builder. The combination of Panels and Panelizer can help in developing templated layouts and landing pages. Also, the Paragraphs module can be used for the creation of custom landing pages. The greatness of the Layout Builder Following are some of the reasons that show how great the Layout Builder is: Source: Dries Buytaert’s blog To lay out all the instances of a specific content type, Layout Builder helps in creating layout templates. Layout Builder allows you to customise these layout templates. You can override these layout templates on a case-by-case basis. It can be utilised to create custom pages. You can create custom, one-off landing pages that are not linked to a content type or structured content. The key to stabilise Layout Builder is to make sure that it passes Drupal’s accessibility gate (Level AA conformance with WCAG and ATAG). So, it will ensure web accessibility standards once stabilised in Drupal 8.7. The Menu Item Extras module is used in Drupal 8 for implementing mega menus through additional fields. In Drupal 8.6, all you need to do for creating a mega menu is to enable Layout Builder for the default menu item view display mode. How to work around with Layout Builder? Follow the following steps to use the Layout Builder for configuring content types and nodes: 1. In the first step, you start by enabling the Layout Builder module. Source: OSTraining2. This is followed by content creation. This requires the installation of Devel module where you enable Devel and Devel generate parts of the plugin. This, then, helps in generating articles. Source: OSTraining3. Then, the layout of the article content type is configured. Source: OSTraining4. Finally, the layout of a single node is configured. Source: OSTrainingConclusion There is no doubt that Drupal’s current site building and content authoring capabilities are great. But Layout Builder will transform the whole experience of creating pages with its simple and intuitive tools. Opensense Labs has been offering a suite of services to help organisations lead their ambitious plans of digital transformation. Contact us at [email protected] to dive into the world of Layout Builder and get the best out of it. blog banner blog image Layout Builder Website layout Drupal Layout Drupal module Drupal 8 Blog Type Articles Is it a good read ? On [Less]
Posted over 5 years ago
In software just about all project management methodologies get labeled one of two things: Agile or Waterfall. There are formal definitions of both labels, but in practice few companies stick to those definitions particularly in the world of ... [More] consulting. For people who really care about such things, there are actually many more methodologies out there but largely for marketing reasons we call any process that’s linear in nature Waterfall, and any that is iterative we call Agile. Failure within project teams leading to disasters is so common and basic that not only is there a cartoon about it but there is a web site dedicated to generating your own versions of that cartoon (http://projectcartoon.com/). Among consultants I have rarely seen a company that is truly 100% agile or 100% waterfall. In fact I’ve rarely seen a shop that’s close enough to the formal structures of those methodologies to really accurately claim to be one or the other. Nearly all consultancies are some kind of blent of a linear process with stages (sometimes called “a waterfall phase” or “a planning phase”) followed by an iterative process with lots of non-developer input into partially completed features (often called an “agile phase” or “build phase”). Depending on the agency they might cut up the planning into the start of each sprint or they might move it all to the beginning as a separate project phase. Done well it can allow you to merge the highly complex needs of an organization with the predefined structures of an existing platform. Done poorly it can it look like you tried to force a square peg into a round hole. You can see evidence of this around the internet in the articles trying to help you pick a methodology and in the variations on Agile that have been attempted to try to adapt the process to the reality many consultants face. In 2001 the Agile Manifesto changed how we talk about project management. It challenged standing doctrine about how software development should be done and moved away from trying to mirror manufacturing processes. As the methodology around agile evolved, and proved itself impressively effective for certain projects, it drew adherents and advocates who preach Agile and Scrum structures as rigid rules to be followed. Meanwhile older project methodologies were largely relabeled “Waterfall” and dragged through the mud as out of date and likely to lead to project failure. But after all this time Agile hasn’t actually won as the only truly useful process because it doesn’t actually work for all projects and all project teams. Particularly among consulting agencies that work on complex platforms like Drupal and Salesforce, you find that regardless of the label the company uses they probably have a mix linear planning with iterative development – or they fail a lot. Agile works best when you start from scratch and you have a talented team trying to solve a unique problem. Anytime you are building on a mature software platform you are at least a few hundred thousand hours into development before you have your first meeting. These platforms have large feature sets that deliver lots of the functionality needed for most projects just through careful planning and basic configuration – that’s the whole point of using them. So on any enterprise scale data system you have to do a great deal of planning before you start creating the finished product. If you don’t plan ahead enough to have a generalized, but complete, picture of what you’re building you will discover very large gaps after far too many pieces have been built to ellagently close them, or your solution will have been built far more generically than needed – introducing significant complexity for very little gain. I’ve seen people re-implement features of Drupal within other features of Drupal just to deal with changing requirements or because a major feature was skipped in planning. So those early planning stages are important, but they also need to leave space for new insights into how best to meet the client’s need and discovery of true errors after the planning stage is complete. Once you have a good plan the team can start to build. But you cannot simply hand a developer the design and say “do this” because your “this” is only as perfect as you are and your plan does not cover all the details. The developer will see things missed during planning, or have questions that everyone else knows but you didn’t think to write down (and if you wrote down every answer to every possible question, you wrote a document no one bothered to actually read). The team needs to implement part of the solution, check with the client to make sure it’s right, adjust to mistakes, and repeat – a very agile-like process that makes waterfall purists uncomfortable because it means the plan they are working from will change. In all this you also have a client to keep happy and help make successful – that’s why they hired someone in the first place. Giving them a plan that shows you know what they want they are reassured early in the project that you share their vision for a final solution. Being able to see that plan come together while giving chances to refine the details allows your to deliver the best product you are able. Agile was supposed to fix all our problems, but didn’t. The methodologies used before were supposed to prevent all the problems that agile was trying to fix, but didn’t. But using waterfall-like planning at the start of your project with agile-ish implementation you can combine the best of both approaches giving you the best chances for success.  We all do it, it is about time we all admit it is what we do. Cartoon from CommitStrip [Less]
Posted over 5 years ago
Many of Acquia's customers have hundreds or even thousands of sites, which vary in terms of scale, functionality, longevity and complexity. One thing that is very unique about Acquia is that we can help organizations scale from small to extremely ... [More] large, one to many, and coupled to decoupled. This scalability and flexibility is quite unique, and allows organizations to standardize on a single web platform. Standardizing on a single web platform not only removes the complexity from having to manage dozens of different technology stacks and teams, but also enables organizations to innovate faster. A great example is NBC Sports Digital. Not only does NBC Sports Digital have to manage dozens of sites across 30,000 sporting events each year, but it also has some of the most trafficked sites in the world. In 2018, Acquia supported NBC Sports Digital as it provided fans with unparalleled coverage of Super Bowl LII, the Pyeongchang Winter Games and the 2018 World Cup. As quoted in NBC Sport's press release, NBC Sports Digital streamed more than 4.37 billion live minutes of video, served 93 million unique users, and delivered 721 million minutes of desktop video streamed. These are some of the highest trafficked events in the history of the web, and I'm very proud that they are powered by Drupal and Acquia. To learn more about how Acquia helps NBC Sports Digital deliver more than 10,000 sporting events every year, watch my conversation with Eric Black, CTO of NBC Sports Digital, in the video below: Not every organization gets to entertain 100 million viewers around the world, but every business has its own World Cup. Whether it's Black Friday, Mother's Day, a new product launch or breaking news, we offer our customers the tools and services necessary to optimize efficiency and provide flexibility at any scale. [Less]